librustc: Enforce that extern mod directives come first, then use directives, then items.

Resolve them in this order as well.
This commit is contained in:
Patrick Walton 2013-03-26 19:53:33 -07:00
parent 8b56a8380b
commit 0a4d0f37ca
14 changed files with 332 additions and 335 deletions

View file

@ -22,12 +22,6 @@ extern mod std(vers = "0.6");
use core::*;
pub mod procsrv;
pub mod util;
pub mod header;
pub mod runtest;
pub mod common;
pub mod errors;
use std::getopts;
use std::test;
@ -43,6 +37,13 @@ use common::mode_debug_info;
use common::mode;
use util::logv;
pub mod procsrv;
pub mod util;
pub mod header;
pub mod runtest;
pub mod common;
pub mod errors;
pub fn main() {
let args = os::args();
let config = parse_config(args);

View file

@ -65,6 +65,45 @@ they contained the following prologue:
#[allow(deprecated_mutable_fields)];
#[allow(deprecated_drop)];
// Make core testable by not duplicating lang items. See #2912
#[cfg(test)] extern mod realcore(name = "core", vers = "0.6");
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use cmp = realcore::cmp;
/* Reexported core operators */
pub use kinds::{Const, Copy, Owned, Durable};
pub use ops::{Drop};
pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Shl, Shr, Index};
/* Reexported types and traits */
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};
pub use path::Path;
pub use path::GenericPath;
pub use path::WindowsPath;
pub use path::PosixPath;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use str::{StrSlice};
pub use container::{Container, Mutable};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector};
pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
pub use num::NumCast;
pub use ptr::Ptr;
pub use to_str::ToStr;
pub use clone::Clone;
// On Linux, link to the runtime with -lrt.
#[cfg(target_os = "linux")]
#[doc(hidden)]
@ -130,12 +169,6 @@ pub mod managed;
#[cfg(notest)] pub mod ops;
#[cfg(notest)] pub mod cmp;
// Make core testable by not duplicating lang items. See #2912
#[cfg(test)] extern mod realcore(name = "core", vers = "0.6");
#[cfg(test)] pub use kinds = realcore::kinds;
#[cfg(test)] pub use ops = realcore::ops;
#[cfg(test)] pub use cmp = realcore::cmp;
/* Common traits */
@ -189,39 +222,6 @@ pub mod condition;
pub mod logging;
pub mod util;
/* Reexported core operators */
pub use kinds::{Const, Copy, Owned, Durable};
pub use ops::{Drop};
pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Shl, Shr, Index};
/* Reexported types and traits */
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};
pub use path::Path;
pub use path::GenericPath;
pub use path::WindowsPath;
pub use path::PosixPath;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use str::{StrSlice};
pub use container::{Container, Mutable};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector};
pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
pub use num::NumCast;
pub use ptr::Ptr;
pub use to_str::ToStr;
pub use clone::Clone;
/* Unsupported interfaces */
@ -241,7 +241,7 @@ pub mod rt;
// 'core' so that macro-expanded references to core::error and such
// can be resolved within libcore.
#[doc(hidden)]
pub mod core {
mod core {
pub use clone;
pub use cmp;
pub use condition;

View file

@ -15,13 +15,12 @@ use ptr;
#[cfg(notest)] use cmp::{Eq, Ord};
pub mod raw {
use intrinsic::TyDesc;
pub static RC_EXCHANGE_UNIQUE : uint = (-1) as uint;
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
pub static RC_IMMORTAL : uint = 0x77777777;
use intrinsic::TyDesc;
pub struct BoxHeaderRepr {
ref_count: uint,
type_desc: *TyDesc,

View file

@ -1167,14 +1167,6 @@ pub mod consts {
#[cfg(windows)]
pub use os::consts::windows::*;
pub mod unix {
pub static FAMILY: &'static str = "unix";
}
pub mod windows {
pub static FAMILY: &'static str = "windows";
}
#[cfg(target_os = "macos")]
pub use os::consts::macos::*;
@ -1190,6 +1182,26 @@ pub mod consts {
#[cfg(target_os = "win32")]
pub use os::consts::win32::*;
#[cfg(target_arch = "x86")]
pub use os::consts::x86::*;
#[cfg(target_arch = "x86_64")]
pub use os::consts::x86_64::*;
#[cfg(target_arch = "arm")]
pub use os::consts::arm::*;
#[cfg(target_arch = "mips")]
use os::consts::mips::*;
pub mod unix {
pub static FAMILY: &'static str = "unix";
}
pub mod windows {
pub static FAMILY: &'static str = "windows";
}
pub mod macos {
pub static SYSNAME: &'static str = "macos";
pub static DLL_PREFIX: &'static str = "lib";
@ -1226,18 +1238,6 @@ pub mod consts {
}
#[cfg(target_arch = "x86")]
pub use os::consts::x86::*;
#[cfg(target_arch = "x86_64")]
pub use os::consts::x86_64::*;
#[cfg(target_arch = "arm")]
pub use os::consts::arm::*;
#[cfg(target_arch = "mips")]
use os::consts::mips::*;
pub mod x86 {
pub static ARCH: &'static str = "x86";
}

View file

@ -127,6 +127,7 @@ pub enum PatternBindingMode {
ArgumentIrrefutableMode(mode)
}
#[deriving(Eq)]
pub enum Namespace {
TypeNS,
ValueNS
@ -161,7 +162,6 @@ pub enum NameDefinition {
NoNameDefinition, //< The name was unbound.
ChildNameDefinition(def), //< The name identifies an immediate child.
ImportNameDefinition(def) //< The name identifies an import.
}
#[deriving(Eq)]
@ -177,15 +177,9 @@ pub enum SelfBinding {
pub type ResolveVisitor = vt<()>;
#[deriving(Eq)]
pub enum ImportDirectiveNS {
TypeNSOnly,
AnyNS
}
/// Contains data for specific types of import directives.
pub enum ImportDirectiveSubclass {
SingleImport(ident /* target */, ident /* source */, ImportDirectiveNS),
SingleImport(ident /* target */, ident /* source */),
GlobImport
}
@ -210,9 +204,9 @@ pub impl<T> ResolveResult<T> {
}
pub enum TypeParameters<'self> {
NoTypeParameters, //< No type parameters.
NoTypeParameters, //< No type parameters.
HasTypeParameters(&'self Generics, //< Type parameters.
node_id, //< ID of the enclosing item
node_id, //< ID of the enclosing item
// The index to start numbering the type parameters at.
// This is zero if this is the outermost set of type
@ -458,6 +452,10 @@ pub struct Module {
children: @mut LinearMap<ident, @mut NameBindings>,
imports: @mut ~[@ImportDirective],
// The external module children of this node that were declared with
// `extern mod`.
external_module_children: @mut LinearMap<ident, @mut Module>,
// The anonymous children of this node. Anonymous children are pseudo-
// modules that are implicitly created around items contained within
// blocks.
@ -495,6 +493,7 @@ pub fn Module(parent_link: ParentLink,
kind: kind,
children: @mut LinearMap::new(),
imports: @mut ~[],
external_module_children: @mut LinearMap::new(),
anonymous_children: @mut LinearMap::new(),
import_resolutions: @mut LinearMap::new(),
glob_count: 0,
@ -968,17 +967,23 @@ pub impl Resolver {
return (child, new_parent);
}
Some(child) => {
// Enforce the duplicate checking mode. If we're requesting
// duplicate module checking, check that there isn't a module
// in the module with the same name. If we're requesting
// duplicate type checking, check that there isn't a type in
// the module with the same name. If we're requesting
// duplicate value checking, check that there isn't a value in
// the module with the same name. If we're requesting
// duplicate type checking and duplicate value checking, check
// that there isn't a duplicate type and a duplicate value
// with the same name. If no duplicate checking was requested
// at all, do nothing.
// Enforce the duplicate checking mode:
//
// * If we're requesting duplicate module checking, check that
// there isn't a module in the module with the same name.
//
// * If we're requesting duplicate type checking, check that
// there isn't a type in the module with the same name.
//
// * If we're requesting duplicate value checking, check that
// there isn't a value in the module with the same name.
//
// * If we're requesting duplicate type checking and duplicate
// value checking, check that there isn't a duplicate type
// and a duplicate value with the same name.
//
// * If no duplicate checking was requested at all, do
// nothing.
let mut is_duplicate = false;
match duplicate_checking_mode {
@ -1432,16 +1437,10 @@ pub impl Resolver {
let module_ = self.get_module_from_parent(parent);
let state = @mut ImportState();
match view_path.node {
view_path_simple(binding, full_path, ns, _) => {
let ns = match ns {
module_ns => TypeNSOnly,
type_value_ns => AnyNS
};
view_path_simple(binding, full_path, _, _) => {
let source_ident = *full_path.idents.last();
let subclass = @SingleImport(binding,
source_ident,
ns);
source_ident);
self.build_import_directive(privacy,
module_,
module_path,
@ -1452,9 +1451,7 @@ pub impl Resolver {
view_path_list(_, ref source_idents, _) => {
for (*source_idents).each |source_ident| {
let name = source_ident.node.name;
let subclass = @SingleImport(name,
name,
AnyNS);
let subclass = @SingleImport(name, name);
self.build_import_directive(privacy,
module_,
copy module_path,
@ -1479,25 +1476,21 @@ pub impl Resolver {
match find_extern_mod_stmt_cnum(self.session.cstore,
node_id) {
Some(crate_id) => {
let (child_name_bindings, new_parent) =
self.add_child(name, parent, ForbidDuplicateTypes,
view_item.span);
let def_id = def_id { crate: crate_id, node: 0 };
let parent_link = ModuleParentLink
(self.get_module_from_parent(new_parent), name);
child_name_bindings.define_module(Public,
parent_link,
(self.get_module_from_parent(parent), name);
let external_module = @mut Module(parent_link,
Some(def_id),
NormalModuleKind,
view_item.span);
self.build_reduced_graph_for_external_crate
(child_name_bindings.get_module());
}
None => {
/* Ignore. */
NormalModuleKind);
parent.external_module_children.insert(
name,
external_module);
self.build_reduced_graph_for_external_crate(
external_module);
}
None => {} // Ignore.
}
}
}
@ -1869,7 +1862,7 @@ pub impl Resolver {
// the appropriate flag.
match *subclass {
SingleImport(target, _, _) => {
SingleImport(target, _) => {
debug!("(building import directive) building import \
directive: privacy %? %s::%s",
privacy,
@ -2020,7 +2013,7 @@ pub impl Resolver {
subclass: ImportDirectiveSubclass)
-> @~str {
match subclass {
SingleImport(_target, source, _ns) => self.session.str_of(source),
SingleImport(_target, source) => self.session.str_of(source),
GlobImport => @~"*"
}
}
@ -2080,21 +2073,13 @@ pub impl Resolver {
// within. Attempt to resolve the import within it.
match *import_directive.subclass {
SingleImport(target, source, AnyNS) => {
SingleImport(target, source) => {
resolution_result =
self.resolve_single_import(module_,
containing_module,
target,
source);
}
SingleImport(target, source, TypeNSOnly) => {
resolution_result =
self.resolve_single_module_import(
module_,
containing_module,
target,
source);
}
GlobImport => {
let span = import_directive.span;
let privacy = import_directive.privacy;
@ -2139,6 +2124,19 @@ pub impl Resolver {
return resolution_result;
}
fn create_name_bindings_from_module(module: @mut Module) -> NameBindings {
NameBindings {
type_def: Some(TypeNsDef {
privacy: Public,
module_def: Some(module),
type_def: None,
}),
value_def: None,
type_span: None,
value_span: None,
}
}
fn resolve_single_import(@mut self,
module_: @mut Module,
containing_module: @mut Module,
@ -2261,6 +2259,25 @@ pub impl Resolver {
}
}
// If we didn't find a result in the type namespace, search the
// external modules.
match type_result {
BoundResult(*) => {}
_ => {
match containing_module.external_module_children
.find(&source) {
None => {} // Continue.
Some(module) => {
let name_bindings =
@mut Resolver::create_name_bindings_from_module(
*module);
type_result = BoundResult(containing_module,
name_bindings);
}
}
}
}
// We've successfully resolved the import. Write the results in.
fail_unless!(module_.import_resolutions.contains_key(&target));
let import_resolution = module_.import_resolutions.get(&target);
@ -2332,135 +2349,9 @@ pub impl Resolver {
return Success(());
}
fn resolve_single_module_import(@mut self,
module_: @mut Module,
containing_module: @mut Module,
target: ident,
source: ident)
-> ResolveResult<()> {
debug!("(resolving single module import) resolving `%s` = `%s::%s` \
from `%s`",
*self.session.str_of(target),
self.module_to_str(containing_module),
*self.session.str_of(source),
self.module_to_str(module_));
// We need to resolve the module namespace for this to succeed.
let mut module_result = UnknownResult;
// Search for direct children of the containing module.
match containing_module.children.find(&source) {
None => {
// Continue.
}
Some(child_name_bindings) => {
if child_name_bindings.defined_in_namespace(TypeNS) {
module_result = BoundResult(containing_module,
*child_name_bindings);
}
}
}
// Unless we managed to find a result, search imports as well.
match module_result {
BoundResult(*) => {
// Continue.
}
_ => {
// If there is an unresolved glob at this point in the
// containing module, bail out. We don't know enough to be
// able to resolve this import.
if containing_module.glob_count > 0 {
debug!("(resolving single module import) unresolved \
glob; bailing out");
return Indeterminate;
}
// Now search the exported imports within the containing
// module.
match containing_module.import_resolutions.find(&source) {
None => {
// The containing module definitely doesn't have an
// exported import with the name in question. We can
// therefore accurately report that the names are
// unbound.
if module_result.is_unknown() {
module_result = UnboundResult;
}
}
Some(import_resolution)
if import_resolution.outstanding_references
== 0 => {
// The name is an import which has been fully
// resolved. We can, therefore, just follow it.
if module_result.is_unknown() {
match (*import_resolution).target_for_namespace(
TypeNS) {
None => {
module_result = UnboundResult;
}
Some(target) => {
import_resolution.state.used = true;
module_result = BoundResult
(target.target_module,
target.bindings);
}
}
}
}
Some(_) => {
// The import is unresolved. Bail out.
debug!("(resolving single module import) unresolved \
import; bailing out");
return Indeterminate;
}
}
}
}
// We've successfully resolved the import. Write the results in.
fail_unless!(module_.import_resolutions.contains_key(&target));
let import_resolution = module_.import_resolutions.get(&target);
match module_result {
BoundResult(target_module, name_bindings) => {
debug!("(resolving single import) found module binding");
import_resolution.type_target =
Some(Target(target_module, name_bindings));
}
UnboundResult => {
debug!("(resolving single import) didn't find module \
binding");
}
UnknownResult => {
fail!(~"module result should be known at this point");
}
}
let i = import_resolution;
if i.type_target.is_none() {
// If this name wasn't found in the type namespace, it's
// definitely unresolved.
return Failed;
}
fail_unless!(import_resolution.outstanding_references >= 1);
import_resolution.outstanding_references -= 1;
debug!("(resolving single module import) successfully resolved \
import");
return Success(());
}
/**
* Resolves a glob import. Note that this function cannot fail; it either
* succeeds or bails out (as importing * from an empty module or a module
* that exports nothing is valid).
*/
// Resolves a glob import. Note that this function cannot fail; it either
// succeeds or bails out (as importing * from an empty module or a module
// that exports nothing is valid).
fn resolve_glob_import(@mut self,
privacy: Privacy,
module_: @mut Module,
@ -2535,8 +2426,8 @@ pub impl Resolver {
}
}
// Add all children from the containing module.
for containing_module.children.each |&(ident, name_bindings)| {
let merge_import_resolution = |ident,
name_bindings: @mut NameBindings| {
let mut dest_import_resolution;
match module_.import_resolutions.find(ident) {
None => {
@ -2563,13 +2454,26 @@ pub impl Resolver {
if name_bindings.defined_in_public_namespace(ValueNS) {
debug!("(resolving glob import) ... for value target");
dest_import_resolution.value_target =
Some(Target(containing_module, *name_bindings));
Some(Target(containing_module, name_bindings));
}
if name_bindings.defined_in_public_namespace(TypeNS) {
debug!("(resolving glob import) ... for type target");
dest_import_resolution.type_target =
Some(Target(containing_module, *name_bindings));
Some(Target(containing_module, name_bindings));
}
};
// Add all children from the containing module.
for containing_module.children.each |&(ident, name_bindings)| {
merge_import_resolution(ident, *name_bindings);
}
// Add external module children from the containing module.
for containing_module.external_module_children.each
|&(ident, module)| {
let name_bindings =
@mut Resolver::create_name_bindings_from_module(*module);
merge_import_resolution(ident, name_bindings);
}
debug!("(resolving glob import) successfully resolved import");
@ -2759,7 +2663,6 @@ pub impl Resolver {
// The current module node is handled specially. First, check for
// its immediate children.
match module_.children.find(&name) {
Some(name_bindings)
if name_bindings.defined_in_namespace(namespace) => {
@ -2772,7 +2675,6 @@ pub impl Resolver {
// all its imports in the usual way; this is because chains of
// adjacent import statements are processed as though they mutated the
// current scope.
match module_.import_resolutions.find(&name) {
None => {
// Not found; continue.
@ -2795,6 +2697,19 @@ pub impl Resolver {
}
}
// Search for external modules.
if namespace == TypeNS {
match module_.external_module_children.find(&name) {
None => {}
Some(module) => {
let name_bindings =
@mut Resolver::create_name_bindings_from_module(
*module);
return Success(Target(module_, name_bindings));
}
}
}
// Finally, proceed up the scope chain looking for parent modules.
let mut search_module = module_;
loop {
@ -3027,7 +2942,8 @@ pub impl Resolver {
// Check the list of resolved imports.
match module_.import_resolutions.find(&name) {
Some(import_resolution) => {
if import_resolution.outstanding_references != 0 {
if import_resolution.privacy == Public &&
import_resolution.outstanding_references != 0 {
debug!("(resolving name in module) import \
unresolved; bailing out");
return Indeterminate;
@ -3054,8 +2970,19 @@ pub impl Resolver {
}
}
}
None => {
// Continue.
None => {} // Continue.
}
// Finally, search through external children.
if namespace == TypeNS {
match module_.external_module_children.find(&name) {
None => {}
Some(module) => {
let name_bindings =
@mut Resolver::create_name_bindings_from_module(
*module);
return Success(Target(module_, name_bindings));
}
}
}
@ -4541,20 +4468,31 @@ pub impl Resolver {
(Some(_), _) | (None, _) => {
// This can happen with external impls, due to
// the imperfect way we read the metadata.
return NoNameDefinition;
}
}
}
None => {
return NoNameDefinition;
None => {}
}
}
Some(_) | None => {} // Continue.
}
// Finally, search through external children.
if namespace == TypeNS {
match containing_module.external_module_children.find(&name) {
None => {}
Some(module) => {
match module.def_id {
None => {} // Continue.
Some(def_id) => {
return ChildNameDefinition(def_mod(def_id));
}
}
}
}
Some(_) | None => {
return NoNameDefinition;
}
}
return NoNameDefinition;
}
fn intern_module_part_of_path(@mut self, path: @path) -> ~[ident] {

View file

@ -28,11 +28,26 @@
#[no_core];
extern mod core(vers = "0.6");
use core::*;
extern mod std(vers = "0.6");
extern mod syntax(vers = "0.6");
use core::prelude::*;
use driver::driver::{host_triple, optgroups, early_error};
use driver::driver::{str_input, file_input, build_session_options};
use driver::driver::{build_session, build_configuration, parse_pretty};
use driver::driver::{pp_mode, pretty_print_input, list_metadata};
use driver::driver::{compile_input};
use driver::session;
use middle::lint;
use core::io::ReaderUtil;
use core::result::{Ok, Err};
use std::getopts::{groups, opt_present};
use std::getopts;
use syntax::codemap;
use syntax::diagnostic;
pub mod middle {
pub mod trans {
pub mod macros;
@ -123,23 +138,6 @@ pub mod lib {
pub mod llvm;
}
use core::prelude::*;
use driver::driver::{host_triple, optgroups, early_error};
use driver::driver::{str_input, file_input, build_session_options};
use driver::driver::{build_session, build_configuration, parse_pretty};
use driver::driver::{pp_mode, pretty_print_input, list_metadata};
use driver::driver::{compile_input};
use driver::session;
use middle::lint;
use core::io::ReaderUtil;
use core::result::{Ok, Err};
use std::getopts::{groups, opt_present};
use std::getopts;
use syntax::codemap;
use syntax::diagnostic;
pub fn version(argv0: &str) {
let mut vers = ~"unknown version";
let env_vers = env!("CFG_VERSION");
@ -202,7 +200,7 @@ pub fn describe_debug_flags() {
pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) {
// Don't display log spew by default. Can override with RUST_LOG.
logging::console_off();
::core::logging::console_off();
let mut args = /*bad*/copy *args;
let binary = args.shift();

View file

@ -28,6 +28,10 @@ extern mod std(vers = "0.6");
extern mod rustc(vers = "0.6");
extern mod syntax(vers = "0.6");
use config::Config;
use doc::Item;
use doc::ItemUtils;
use core::*;
pub mod pass;
@ -59,10 +63,6 @@ pub mod escape_pass;
pub mod prune_private_pass;
pub mod util;
use doc::ItemUtils;
use doc::Item;
use config::Config;
pub fn main() {
let args = os::args();

View file

@ -27,6 +27,7 @@ extern mod rustc(vers = "0.6");
extern mod syntax(vers = "0.6");
use core::*;
use core::container::Map;
use core::hashmap::linear::LinearMap;
use core::io::{ReaderUtil, WriterUtil};
use rustc::driver::{driver, session};
@ -35,13 +36,12 @@ use std::net::url;
use std::{json, semver, getopts};
use syntax::codemap::spanned;
use syntax::{ast, attr, codemap, diagnostic, parse, visit};
use core::container::Map;
use util::Package;
mod usage;
mod util;
use util::Package;
struct PackageScript {
id: ~str,
name: ~str,

View file

@ -33,7 +33,7 @@ not required in or otherwise suitable for the core library.
#[no_core];
extern mod core(vers = "0.6");
use core::*;
use core::prelude::*;
pub mod uv_ll;

View file

@ -563,7 +563,7 @@ pub fn run_test(force_ignore: bool,
fn run_test_inner(desc: TestDesc,
monitor_ch: SharedChan<MonitorMsg>,
testfn: ~fn()) {
let testfn_cell = ::cell::Cell(testfn);
let testfn_cell = ::core::cell::Cell(testfn);
do task::spawn {
let mut result_future = None; // task::future_result(builder);
task::task().unlinked().future_result(|+r| {

View file

@ -120,6 +120,7 @@ pub enum item_or_view_item {
iovi_view_item(@view_item)
}
#[deriving(Eq)]
enum view_item_parse_mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED,
FOREIGN_ITEMS_ALLOWED,
@ -4324,48 +4325,91 @@ pub impl Parser {
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true,
FOREIGN_ITEMS_ALLOWED => false
};
let restricted_to_imports = match mode {
IMPORTS_AND_ITEMS_ALLOWED => true,
VIEW_ITEMS_AND_ITEMS_ALLOWED |
FOREIGN_ITEMS_ALLOWED => false
};
let foreign_items_allowed = match mode {
FOREIGN_ITEMS_ALLOWED => true,
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false
};
// First, parse view items.
let mut (view_items, items, foreign_items) = (~[], ~[], ~[]);
loop {
match self.parse_item_or_view_item(/*bad*/ copy attrs,
items_allowed,
foreign_items_allowed,
macros_allowed) {
iovi_none =>
break,
iovi_view_item(view_item) => {
if restricted_to_imports {
match view_item.node {
view_item_use(*) => {}
view_item_extern_mod(*) =>
self.fatal(~"\"extern mod\" \
declarations are not \
allowed here")
}
let mut done = false;
if mode != FOREIGN_ITEMS_ALLOWED {
let mut extern_mod_allowed = match mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED => true,
IMPORTS_AND_ITEMS_ALLOWED => false,
FOREIGN_ITEMS_ALLOWED => {
self.bug(~"couldn't get here with FOREIGN_ITEMS_ALLOWED")
}
};
loop {
match self.parse_item_or_view_item(/*bad*/ copy attrs,
items_allowed,
foreign_items_allowed,
macros_allowed) {
iovi_none => {
done = true;
break;
}
iovi_view_item(view_item) => {
match view_item.node {
view_item_use(*) => {
// `extern mod` must precede `use`.
extern_mod_allowed = false;
}
view_item_extern_mod(*)
if !extern_mod_allowed => {
self.span_err(view_item.span,
~"\"extern mod\" \
declarations are not \
allowed here");
}
view_item_extern_mod(*) => {}
}
view_items.push(view_item);
}
iovi_item(item) => {
fail_unless!(items_allowed);
items.push(item);
attrs = self.parse_outer_attributes();
break;
}
iovi_foreign_item(foreign_item) => {
fail_unless!(foreign_items_allowed);
foreign_items.push(foreign_item);
attrs = self.parse_outer_attributes();
break;
}
view_items.push(view_item);
}
iovi_item(item) => {
fail_unless!(items_allowed);
items.push(item)
}
iovi_foreign_item(foreign_item) => {
fail_unless!(foreign_items_allowed);
foreign_items.push(foreign_item);
}
attrs = self.parse_outer_attributes();
}
}
// Next, parse items.
if !done {
loop {
match self.parse_item_or_view_item(/*bad*/ copy attrs,
items_allowed,
foreign_items_allowed,
macros_allowed) {
iovi_none => break,
iovi_view_item(view_item) => {
self.span_err(view_item.span,
~"`use` and `extern mod` declarations \
must precede items");
view_items.push(view_item);
}
iovi_item(item) => {
fail_unless!(items_allowed);
items.push(item)
}
iovi_foreign_item(foreign_item) => {
fail_unless!(foreign_items_allowed);
foreign_items.push(foreign_item);
}
}
attrs = self.parse_outer_attributes();
}
attrs = self.parse_outer_attributes();
}
ParsedItemsAndViewItems {

View file

@ -26,10 +26,10 @@
#[no_core];
extern mod core(vers = "0.6");
use core::*;
extern mod std(vers = "0.6");
use core::*;
pub mod syntax {
pub use ext;
pub use parse;

View file

@ -0,0 +1,6 @@
#[crate_type="lib"];
pub mod extern_mod_ordering_lib {
pub fn f() {}
}

View file

@ -0,0 +1,11 @@
// aux-build:extern_mod_ordering_lib.rs
// xfail-fast
extern mod extern_mod_ordering_lib;
use extern_mod_ordering_lib::extern_mod_ordering_lib;
fn main() {
extern_mod_ordering_lib::f();
}