diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5b655522f34..2cc39412182 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,6 +50,7 @@ use std::collections::BTreeMap; use std::iter; use syntax::ast::*; +use syntax::errors; use syntax::ptr::P; use syntax::codemap::{respan, Spanned}; use syntax::parse::token; @@ -60,7 +61,7 @@ pub struct LoweringContext<'a> { crate_root: Option<&'static str>, // Use to assign ids to hir nodes that do not directly correspond to an ast node - id_assigner: &'a NodeIdAssigner, + sess: Option<&'a Session>, // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. @@ -99,7 +100,6 @@ fn definitions(&mut self) -> Option<&mut Definitions> { pub fn lower_crate(sess: &Session, krate: &Crate, - id_assigner: &NodeIdAssigner, resolver: &mut Resolver) -> hir::Crate { // We're constructing the HIR here; we don't care what we will @@ -115,17 +115,17 @@ pub fn lower_crate(sess: &Session, } else { Some("std") }, - id_assigner: id_assigner, + sess: Some(sess), parent_def: None, resolver: resolver, }.lower_crate(krate) } impl<'a> LoweringContext<'a> { - pub fn testing_context(id_assigner: &'a NodeIdAssigner, resolver: &'a mut Resolver) -> Self { + pub fn testing_context(resolver: &'a mut Resolver) -> Self { LoweringContext { crate_root: None, - id_assigner: id_assigner, + sess: None, parent_def: None, resolver: resolver, } @@ -161,7 +161,12 @@ fn visit_item(&mut self, item: &Item) { } fn next_id(&self) -> NodeId { - self.id_assigner.next_node_id() + self.sess.map(Session::next_node_id).unwrap_or(0) + } + + fn diagnostic(&self) -> &errors::Handler { + self.sess.map(Session::diagnostic) + .unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics")) } fn str_to_ident(&self, s: &'static str) -> Name { @@ -786,7 +791,7 @@ fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { match hir_sig.decl.get_self().map(|eself| eself.node) { Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { - self.id_assigner.diagnostic().span_err(sig.decl.inputs[0].ty.span, + self.diagnostic().span_err(sig.decl.inputs[0].ty.span, "the type placeholder `_` is not allowed within types on item signatures"); } _ => {} @@ -1212,7 +1217,7 @@ fn make_struct(this: &mut LoweringContext, make_struct(self, e, &["RangeInclusive", "NonEmpty"], &[("start", e1), ("end", e2)]), - _ => panic!(self.id_assigner.diagnostic() + _ => panic!(self.diagnostic() .span_fatal(e.span, "inclusive range with no end")), }; } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index ccb3e154d92..2b89695ab41 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -25,15 +25,15 @@ pub struct DefCollector<'ast> { // If we are walking HIR (c.f., AST), we need to keep a reference to the // crate. hir_crate: Option<&'ast hir::Crate>, - pub definitions: Definitions, + definitions: &'ast mut Definitions, parent_def: Option, } impl<'ast> DefCollector<'ast> { - pub fn root() -> DefCollector<'ast> { + pub fn root(definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, - definitions: Definitions::new(), + definitions: definitions, parent_def: None, }; let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); @@ -48,7 +48,7 @@ pub fn root() -> DefCollector<'ast> { pub fn extend(parent_node: NodeId, parent_def_path: DefPath, parent_def_id: DefId, - definitions: Definitions) + definitions: &'ast mut Definitions) -> DefCollector<'ast> { let mut collector = DefCollector { hir_crate: None, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d66df3e4e8f..3317585f820 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -10,8 +10,9 @@ use middle::cstore::LOCAL_CRATE; use hir::def_id::{DefId, DefIndex}; +use hir::map::def_collector::DefCollector; use rustc_data_structures::fnv::FnvHashMap; -use syntax::ast; +use syntax::{ast, visit}; use syntax::parse::token::InternedString; use util::nodemap::NodeMap; @@ -189,6 +190,11 @@ pub fn new() -> Definitions { } } + pub fn collect(&mut self, krate: &ast::Crate) { + let mut def_collector = DefCollector::root(self); + visit::walk_crate(&mut def_collector, krate); + } + /// Get the number of definitions. pub fn len(&self) -> usize { self.data.len() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f9fb8ac66b7..960e32ae99f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -24,7 +24,6 @@ use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; use syntax::codemap::Spanned; -use syntax::visit; use syntax_pos::Span; use hir::*; @@ -780,12 +779,6 @@ fn new_span(&mut self, span: Span) -> Span { } } -pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions { - let mut def_collector = DefCollector::root(); - visit::walk_crate(&mut def_collector, krate); - def_collector.definitions -} - pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> { @@ -842,13 +835,12 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, let ii = map.forest.inlined_items.alloc(ii); let ii_parent_id = fld.new_id(DUMMY_NODE_ID); - let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()); + let defs = &mut *map.definitions.borrow_mut(); let mut def_collector = DefCollector::extend(ii_parent_id, parent_def_path.clone(), parent_def_id, defs); def_collector.walk_item(ii, map.krate()); - *map.definitions.borrow_mut() = def_collector.definitions; let mut collector = NodeCollector::extend(map.krate(), ii, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 77259cea24d..fdaf182c605 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use util::nodemap::{NodeMap, FnvHashMap}; use mir::transform as mir_pass; -use syntax::ast::{NodeId, NodeIdAssigner, Name}; +use syntax::ast::{NodeId, Name}; use errors::{self, DiagnosticBuilder}; use errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; use syntax::json::JsonEmitter; @@ -272,6 +272,9 @@ pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId { id } + pub fn next_node_id(&self) -> NodeId { + self.reserve_node_ids(1) + } pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } @@ -345,20 +348,6 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { } } -impl NodeIdAssigner for Session { - fn next_node_id(&self) -> NodeId { - self.reserve_node_ids(1) - } - - fn peek_node_id(&self) -> NodeId { - self.next_node_id.get().checked_add(1).unwrap() - } - - fn diagnostic(&self) -> &errors::Handler { - self.diagnostic() - } -} - fn split_msg_into_multilines(msg: &str) -> Option { // Conditions for enabling multi-line errors: if !msg.contains("mismatched types") && diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c03903515ab..6c37662206c 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -543,54 +543,47 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { // unary neg literals already got their sign during creation - match inner.node { - hir::ExprLit(ref lit) => { - use syntax::ast::*; - use syntax::ast::LitIntType::*; - const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; - const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; - const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; - const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; - match (&lit.node, ety.map(|t| &t.sty)) { - (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | - (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { - return Ok(Integral(I8(::std::i8::MIN))) - }, - (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | - (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { - return Ok(Integral(I16(::std::i16::MIN))) - }, - (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | - (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { - return Ok(Integral(I32(::std::i32::MIN))) - }, - (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | - (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { - return Ok(Integral(I64(::std::i64::MIN))) - }, - (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | - (&LitKind::Int(n, Signed(IntTy::Is)), _) => { - match tcx.sess.target.int_type { - IntTy::I16 => if n == I16_OVERFLOW { - return Ok(Integral(Isize(Is16(::std::i16::MIN)))); - }, - IntTy::I32 => if n == I32_OVERFLOW { - return Ok(Integral(Isize(Is32(::std::i32::MIN)))); - }, - IntTy::I64 => if n == I64_OVERFLOW { - return Ok(Integral(Isize(Is64(::std::i64::MIN)))); - }, - _ => bug!(), - } - }, - _ => {}, - } - }, - hir::ExprUnary(hir::UnNeg, ref inner) => { - // skip `--$expr` - return eval_const_expr_partial(tcx, inner, ty_hint, fn_args); - }, - _ => {}, + if let hir::ExprLit(ref lit) = inner.node { + use syntax::ast::*; + use syntax::ast::LitIntType::*; + const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; + const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; + const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; + const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; + match (&lit.node, ety.map(|t| &t.sty)) { + (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | + (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { + return Ok(Integral(I8(::std::i8::MIN))) + }, + (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | + (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { + return Ok(Integral(I16(::std::i16::MIN))) + }, + (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | + (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { + return Ok(Integral(I32(::std::i32::MIN))) + }, + (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | + (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { + return Ok(Integral(I64(::std::i64::MIN))) + }, + (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | + (&LitKind::Int(n, Signed(IntTy::Is)), _) => { + match tcx.sess.target.int_type { + IntTy::I16 => if n == I16_OVERFLOW { + return Ok(Integral(Isize(Is16(::std::i16::MIN)))); + }, + IntTy::I32 => if n == I32_OVERFLOW { + return Ok(Integral(Isize(Is32(::std::i32::MIN)))); + }, + IntTy::I64 => if n == I64_OVERFLOW { + return Ok(Integral(Isize(Is64(::std::i64::MIN)))); + }, + _ => bug!(), + } + }, + _ => {}, + } } match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { Float(f) => Float(-f), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eb442c0a34e..46009e58130 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepGraph; use rustc::hir; use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; use rustc::hir::def::DefMap; @@ -27,7 +26,7 @@ use rustc_back::sha2::{Sha256, Digest}; use rustc_borrowck as borrowck; use rustc_incremental; -use rustc_resolve as resolve; +use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::macro_import; use rustc_metadata::creader::read_local_crates; use rustc_metadata::cstore::CStore; @@ -49,13 +48,11 @@ use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeIdAssigner}; +use syntax::{ast, diagnostics, visit}; use syntax::attr::{self, AttrMetaMethods}; -use syntax::diagnostics; use syntax::fold::Folder; use syntax::parse::{self, PResult, token}; use syntax::util::node_count::NodeCounter; -use syntax::visit; use syntax; use syntax_ext; @@ -293,7 +290,7 @@ pub struct CompileController<'a> { pub after_analysis: PhaseController<'a>, pub after_llvm: PhaseController<'a>, - pub make_glob_map: resolve::MakeGlobMap, + pub make_glob_map: MakeGlobMap, } impl<'a> CompileController<'a> { @@ -305,7 +302,7 @@ pub fn basic() -> CompileController<'a> { after_hir_lowering: PhaseController::basic(), after_analysis: PhaseController::basic(), after_llvm: PhaseController::basic(), - make_glob_map: resolve::MakeGlobMap::No, + make_glob_map: MakeGlobMap::No, } } } @@ -564,7 +561,7 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, mut krate: ast::Crate, crate_name: &'a str, addl_plugins: Option>, - make_glob_map: resolve::MakeGlobMap) + make_glob_map: MakeGlobMap) -> Result, usize> { let time_passes = sess.time_passes(); @@ -729,13 +726,16 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, krate = assign_node_ids(sess, krate); - // Collect defintions for def ids. - let mut defs = - time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate)); + let resolver_arenas = Resolver::arenas(); + let mut resolver = Resolver::new(sess, make_glob_map, &resolver_arenas); - time(sess.time_passes(), - "external crate/lib resolution", - || read_local_crates(sess, &cstore, &defs, &krate, crate_name, &sess.dep_graph)); + // Collect defintions for def ids. + time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate)); + + time(sess.time_passes(), "external crate/lib resolution", || { + let defs = &resolver.definitions; + read_local_crates(sess, &cstore, defs, &krate, crate_name, &sess.dep_graph) + }); time(sess.time_passes(), "early lint checks", @@ -745,8 +745,14 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, "AST validation", || ast_validation::check_crate(sess, &krate)); - let (analysis, resolutions, hir_forest) = - lower_and_resolve(sess, crate_name, &mut defs, &krate, &sess.dep_graph, make_glob_map); + time(sess.time_passes(), "name resolution", || { + resolver.resolve_crate(&krate); + }); + + // Lower ast -> hir. + let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { + hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph) + }); // Discard MTWT tables that aren't required past lowering to HIR. if !keep_mtwt_tables(sess) { @@ -755,9 +761,20 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, Ok(ExpansionResult { expanded_crate: krate, - defs: defs, - analysis: analysis, - resolutions: resolutions, + defs: resolver.definitions, + analysis: ty::CrateAnalysis { + export_map: resolver.export_map, + access_levels: AccessLevels::default(), + reachable: NodeSet(), + name: crate_name, + glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, + }, + resolutions: Resolutions { + def_map: resolver.def_map, + freevars: resolver.freevars, + trait_map: resolver.trait_map, + maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, + }, hir_forest: hir_forest }) } @@ -809,38 +826,6 @@ fn fold_block(&mut self, block: P) -> P { krate } -pub fn lower_and_resolve<'a>(sess: &Session, - id: &'a str, - defs: &mut hir_map::Definitions, - krate: &ast::Crate, - dep_graph: &DepGraph, - make_glob_map: resolve::MakeGlobMap) - -> (ty::CrateAnalysis<'a>, Resolutions, hir_map::Forest) { - resolve::with_resolver(sess, defs, make_glob_map, |mut resolver| { - time(sess.time_passes(), "name resolution", || { - resolve::resolve_crate(&mut resolver, krate); - }); - - // Lower ast -> hir. - let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - hir_map::Forest::new(lower_crate(sess, krate, sess, &mut resolver), dep_graph) - }); - - (ty::CrateAnalysis { - export_map: resolver.export_map, - access_levels: AccessLevels::default(), - reachable: NodeSet(), - name: &id, - glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, - }, Resolutions { - def_map: resolver.def_map, - freevars: resolver.freevars, - trait_map: resolver.trait_map, - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - }, hir_forest) - }) -} - /// Run the resolution, typechecking, region checking and other /// miscellaneous analysis passes on the crate. Return various /// structures carrying the results of the analysis. diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index dc37bdf6322..7ef00b971c5 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -38,7 +38,6 @@ use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; -use syntax::ast::NodeIdAssigner; use syntax::ptr::P; use syntax_pos; @@ -56,7 +55,6 @@ #[cfg(test)] use std::io::Cursor; #[cfg(test)] use syntax::parse; -#[cfg(test)] use syntax::ast::NodeId; #[cfg(test)] use rustc::hir::print as pprust; #[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; @@ -1295,22 +1293,6 @@ fn name_of(&self, st: &str) -> ast::Name { fn parse_sess(&self) -> &parse::ParseSess { self } } -#[cfg(test)] -struct FakeNodeIdAssigner; - -#[cfg(test)] -// It should go without saying that this may give unexpected results. Avoid -// lowering anything which needs new nodes. -impl NodeIdAssigner for FakeNodeIdAssigner { - fn next_node_id(&self) -> NodeId { - 0 - } - - fn peek_node_id(&self) -> NodeId { - 0 - } -} - #[cfg(test)] fn mk_ctxt() -> parse::ParseSess { parse::ParseSess::new() @@ -1318,9 +1300,8 @@ fn mk_ctxt() -> parse::ParseSess { #[cfg(test)] fn with_testing_context T>(f: F) -> T { - let assigner = FakeNodeIdAssigner; let mut resolver = DummyResolver; - let mut lcx = LoweringContext::testing_context(&assigner, &mut resolver); + let mut lcx = LoweringContext::testing_context(&mut resolver); f(&mut lcx) } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 4e4f6e276d1..3e860150a35 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -16,6 +16,8 @@ register_long_diagnostics! { E0154: r##" +## Note: this error code is no longer emitted by the compiler. + Imports (`use` statements) are not allowed after non-item statements, such as variable declarations and expression statements. @@ -50,6 +52,8 @@ fn f() { "##, E0251: r##" +## Note: this error code is no longer emitted by the compiler. + Two items of the same name cannot be imported without rebinding one of the items under a new local name. @@ -75,9 +79,9 @@ pub mod baz {} Two items of the same name cannot be imported without rebinding one of the items under a new local name. -An example of this error: +Erroneous code example: -```compile_fail +```compile_fail,E0252 use foo::baz; use bar::baz; // error, do `use bar::baz as quux` instead @@ -87,6 +91,41 @@ mod foo { pub struct baz; } +mod bar { + pub mod baz {} +} +``` + +You can use aliases in order to fix this error. Example: + +``` +use foo::baz as foo_baz; +use bar::baz; // ok! + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +Or you can reference the item with its parent: + +``` +use bar::baz; + +fn main() { + let x = foo::baz; // ok! +} + +mod foo { + pub struct baz; +} + mod bar { pub mod baz {} } @@ -95,9 +134,11 @@ pub mod baz {} E0253: r##" Attempt was made to import an unimportable value. This can happen when trying -to import a method from a trait. An example of this error: +to import a method from a trait. -```compile_fail +Erroneous code example: + +```compile_fail,E0253 mod foo { pub trait MyTrait { fn do_something(); @@ -105,6 +146,8 @@ pub trait MyTrait { } use foo::MyTrait::do_something; + +fn main() {} ``` It's invalid to directly import methods belonging to a trait or concrete type. @@ -114,10 +157,10 @@ pub trait MyTrait { You can't import a value whose name is the same as another value defined in the module. -An example of this error: +Erroneous code example: -```compile_fail -use bar::foo; // error, do `use bar::foo as baz` instead +```compile_fail,E0255 +use bar::foo; // error: an item named `foo` is already in scope fn foo() {} @@ -127,9 +170,39 @@ pub fn foo() {} fn main() {} ``` + +You can use aliases in order to fix this error. Example: + +``` +use bar::foo as bar_foo; // ok! + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +Or you can reference the item with its parent: + +``` +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() { + bar::foo(); // we get the item by referring to its parent +} +``` "##, E0256: r##" +## Note: this error code is no longer emitted by the compiler. + You can't import a type or module when the name of the item being imported is the same as another type or submodule defined in the module. @@ -154,9 +227,11 @@ fn main() {} Erroneous code example: -```compile_fail -extern crate a; -extern crate crate_a as a; +```compile_fail,E0259 +extern crate std; +extern crate libc as std; + +fn main() {} ``` The solution is to choose a different name that doesn't conflict with any @@ -165,17 +240,17 @@ fn main() {} Correct example: ```ignore -extern crate a; -extern crate crate_a as other_name; +extern crate std; +extern crate libc as other_name; ``` "##, E0260: r##" The name for an item declaration conflicts with an external crate's name. -For instance: +Erroneous code example: -```ignore +```ignore,E0260 extern crate abc; struct abc; @@ -206,10 +281,10 @@ fn main() {} "##, E0364: r##" -Private items cannot be publicly re-exported. This error indicates that you +Private items cannot be publicly re-exported. This error indicates that you attempted to `pub use` a type or value that was not itself public. -Here is an example that demonstrates the error: +Erroneous code example: ```compile_fail mod foo { @@ -217,17 +292,21 @@ mod foo { } pub use foo::X; + +fn main() {} ``` The solution to this problem is to ensure that the items that you are re-exporting are themselves marked with `pub`: -```ignore +``` mod foo { pub const X: u32 = 1; } pub use foo::X; + +fn main() {} ``` See the 'Use Declarations' section of the reference for more information on @@ -240,25 +319,29 @@ mod foo { Private modules cannot be publicly re-exported. This error indicates that you attempted to `pub use` a module that was not itself public. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0365 mod foo { pub const X: u32 = 1; } pub use foo as foo2; + +fn main() {} ``` The solution to this problem is to ensure that the module that you are re-exporting is itself marked with `pub`: -```ignore +``` pub mod foo { pub const X: u32 = 1; } pub use foo as foo2; + +fn main() {} ``` See the 'Use Declarations' section of the reference for more information @@ -269,9 +352,11 @@ pub mod foo { E0401: r##" Inner items do not inherit type parameters from the functions they are embedded -in. For example, this will not compile: +in. -```compile_fail +Erroneous code example: + +```compile_fail,E0401 fn foo(x: T) { fn bar(y: T) { // T is defined in the "outer" function // .. @@ -282,7 +367,7 @@ fn bar(y: T) { // T is defined in the "outer" function Nor will this: -```compile_fail +```compile_fail,E0401 fn foo(x: T) { type MaybeT = Option; // ... @@ -291,7 +376,7 @@ fn foo(x: T) { Or this: -```compile_fail +```compile_fail,E0401 fn foo(x: T) { struct Foo { x: T, @@ -374,9 +459,11 @@ fn bar(&self, y: T) { "##, E0403: r##" -Some type parameters have the same name. Example of erroneous code: +Some type parameters have the same name. -```compile_fail +Erroneous code example: + +```compile_fail,E0403 fn foo(s: T, u: T) {} // error: the name `T` is already used for a type // parameter in this type parameter list ``` @@ -390,10 +477,11 @@ fn foo(s: T, u: Y) {} // ok! "##, E0404: r##" -You tried to implement something which was not a trait on an object. Example of -erroneous code: +You tried to implement something which was not a trait on an object. -```compile_fail +Erroneous code example: + +```compile_fail,E0404 struct Foo; struct Bar; @@ -416,9 +504,11 @@ impl Foo for Bar { // ok! "##, E0405: r##" -The code refers to a trait that is not in scope. Example of erroneous code: +The code refers to a trait that is not in scope. -```compile_fail +Erroneous code example: + +```compile_fail,E0405 struct Foo; impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope @@ -446,9 +536,11 @@ impl SomeTrait for Foo { // ok! E0407: r##" A definition of a method not in the implemented trait was given in a trait -implementation. Example of erroneous code: +implementation. -```compile_fail +Erroneous code example: + +```compile_fail,E0407 trait Foo { fn a(); } @@ -501,9 +593,9 @@ fn b() {} An "or" pattern was used where the variable bindings are not consistently bound across patterns. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0408 match x { Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is // not bound in pattern #2 @@ -545,9 +637,9 @@ fn b() {} An "or" pattern was used where the variable bindings are not consistently bound across patterns. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0409 let x = (0, 2); match x { (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with @@ -583,9 +675,11 @@ fn b() {} "##, E0411: r##" -The `Self` keyword was used outside an impl or a trait. Erroneous code example: +The `Self` keyword was used outside an impl or a trait. -```compile_fail +Erroneous code example: + +```compile_fail,E0411 ::foo; // error: use of `Self` outside of an impl or trait ``` @@ -639,9 +733,11 @@ trait Baz : Foo + Foo2 { "##, E0412: r##" -The type name used is not in scope. Example of erroneous codes: +The type name used is not in scope. -```compile_fail +Erroneous code examples: + +```compile_fail,E0412 impl Something {} // error: type name `Something` is not in scope // or: @@ -678,9 +774,11 @@ fn foo(x: T) {} // ok! "##, E0415: r##" -More than one function parameter have the same name. Example of erroneous code: +More than one function parameter have the same name. -```compile_fail +Erroneous code example: + +```compile_fail,E0415 fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than // once in this parameter list ``` @@ -693,9 +791,11 @@ fn foo(f: i32, g: i32) {} // ok! "##, E0416: r##" -An identifier is bound more than once in a pattern. Example of erroneous code: +An identifier is bound more than once in a pattern. -```compile_fail +Erroneous code example: + +```compile_fail,E0416 match (1, 2) { (x, x) => {} // error: identifier `x` is bound more than once in the // same pattern @@ -722,9 +822,10 @@ fn foo(f: i32, g: i32) {} // ok! E0422: r##" You are trying to use an identifier that is either undefined or not a struct. -For instance: -``` compile_fail +Erroneous code example: + +``` compile_fail,E0422 fn main () { let x = Foo { x: 1, y: 2 }; } @@ -733,7 +834,7 @@ fn main () { In this case, `Foo` is undefined, so it inherently isn't anything, and definitely not a struct. -```compile_fail +```compile_fail,E0422 fn main () { let foo = 1; let x = foo { x: 1, y: 2 }; @@ -745,10 +846,11 @@ fn main () { "##, E0423: r##" -A `struct` variant name was used like a function name. Example of erroneous -code: +A `struct` variant name was used like a function name. -```compile_fail +Erroneous code example: + +```compile_fail,E0423 struct Foo { a: bool}; let f = Foo(); @@ -767,9 +869,11 @@ fn Foo() -> u32 { 0 } "##, E0424: r##" -The `self` keyword was used in a static method. Example of erroneous code: +The `self` keyword was used in a static method. -```compile_fail +Erroneous code example: + +```compile_fail,E0424 struct Foo; impl Foo { @@ -799,9 +903,11 @@ fn foo(self) { "##, E0425: r##" -An unresolved name was used. Example of erroneous codes: +An unresolved name was used. -```compile_fail +Erroneous code examples: + +```compile_fail,E0425 something_that_doesnt_exist::foo; // error: unresolved name `something_that_doesnt_exist::foo` @@ -857,9 +963,11 @@ mod something_that_does_exist { "##, E0426: r##" -An undeclared label was used. Example of erroneous code: +An undeclared label was used. -```compile_fail +Erroneous code example: + +```compile_fail,E0426 loop { break 'a; // error: use of undeclared label `'a` } @@ -875,10 +983,11 @@ mod something_that_does_exist { "##, E0428: r##" -A type or module has been defined more than once. Example of erroneous -code: +A type or module has been defined more than once. -```compile_fail +Erroneous code example: + +```compile_fail,E0428 struct Bar; struct Bar; // error: duplicate definition of value `Bar` ``` @@ -896,9 +1005,9 @@ mod something_that_does_exist { The `self` keyword cannot appear alone as the last segment in a `use` declaration. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0429 use std::fmt::self; // error: `self` imports are only allowed within a { } list ``` @@ -917,9 +1026,11 @@ mod something_that_does_exist { "##, E0430: r##" -The `self` import appears more than once in the list. Erroneous code example: +The `self` import appears more than once in the list. -```compile_fail +Erroneous code example: + +```compile_fail,E0430 use something::{self, self}; // error: `self` import can only appear once in // the list ``` @@ -933,9 +1044,11 @@ mod something_that_does_exist { "##, E0431: r##" -An invalid `self` import was made. Erroneous code example: +An invalid `self` import was made. -```compile_fail +Erroneous code example: + +```compile_fail,E0431 use {self}; // error: `self` import can only appear in an import list with a // non-empty prefix ``` @@ -945,9 +1058,11 @@ mod something_that_does_exist { "##, E0432: r##" -An import was unresolved. Erroneous code example: +An import was unresolved. -```compile_fail +Erroneous code example: + +```compile_fail,E0432 use something::Foo; // error: unresolved import `something::Foo`. ``` @@ -976,14 +1091,23 @@ mod something { "##, E0433: r##" -Invalid import. Example of erroneous code: +An undeclared type or module was used. -```compile_fail -use something_which_doesnt_exist; -// error: unresolved import `something_which_doesnt_exist` +Erroneous code example: + +```compile_fail,E0433 +let map = HashMap::new(); +// error: failed to resolve. Use of undeclared type or module `HashMap` ``` -Please verify you didn't misspell the import's name. +Please verify you didn't misspell the type/module's name or that you didn't +forgot to import it: + + +``` +use std::collections::HashMap; // HashMap has been imported. +let map: HashMap = HashMap::new(); // So it can be used! +``` "##, E0434: r##" @@ -991,9 +1115,9 @@ mod something { because the variable comes from a dynamic environment. Inner functions do not have access to their containing environment. -Example of erroneous code: +Erroneous code example: -```compile_fail +```compile_fail,E0434 fn foo() { let y = 5; fn bar() -> u32 { @@ -1032,10 +1156,11 @@ fn bar() -> u32 { "##, E0435: r##" -A non-constant value was used to initialise a constant. Example of erroneous -code: +A non-constant value was used to initialise a constant. -```compile_fail +Erroneous code example: + +```compile_fail,E0435 let foo = 42u32; const FOO : u32 = foo; // error: attempt to use a non-constant value in a // constant @@ -1061,9 +1186,9 @@ fn bar() -> u32 { an associated type whose name does not match the name of any associated type in the trait. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0437 trait Foo {} impl Foo for i32 { @@ -1086,9 +1211,9 @@ impl Foo for i32 {} attempted to implement an associated constant whose name does not match the name of any associated constant in the trait. -Here is an example that demonstrates the error: +Erroneous code example: -```compile_fail +```compile_fail,E0438 #![feature(associated_consts)] trait Foo {} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8ffa95ec7e9..ed400af6685 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -47,7 +47,7 @@ use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::ty; use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; @@ -925,7 +925,7 @@ fn intern(&mut self, string: &str, primitive_type: PrimTy) { pub struct Resolver<'a> { session: &'a Session, - definitions: &'a mut Definitions, + pub definitions: Definitions, graph_root: Module<'a>, @@ -1001,7 +1001,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, } -struct ResolverArenas<'a> { +pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, @@ -1079,7 +1079,7 @@ fn record_resolution(&mut self, id: NodeId, def: Def) { } fn definitions(&mut self) -> Option<&mut Definitions> { - Some(self.definitions) + Some(&mut self.definitions) } } @@ -1100,12 +1100,9 @@ fn name(&self) -> Name { } impl<'a> Resolver<'a> { - fn new(session: &'a Session, - definitions: &'a mut Definitions, - make_glob_map: MakeGlobMap, - arenas: &'a ResolverArenas<'a>) - -> Resolver<'a> { - let root_def_id = definitions.local_def_id(CRATE_NODE_ID); + pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>) + -> Resolver<'a> { + let root_def_id = DefId::local(CRATE_DEF_INDEX); let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); let graph_root = arenas.alloc_module(graph_root); @@ -1115,7 +1112,7 @@ fn new(session: &'a Session, Resolver { session: session, - definitions: definitions, + definitions: Definitions::new(), // The outermost module has def ID 0; this is not reflected in the // AST. @@ -1158,7 +1155,7 @@ fn new(session: &'a Session, } } - fn arenas() -> ResolverArenas<'a> { + pub fn arenas() -> ResolverArenas<'a> { ResolverArenas { modules: arena::TypedArena::new(), local_modules: RefCell::new(Vec::new()), @@ -1168,6 +1165,27 @@ fn arenas() -> ResolverArenas<'a> { } } + /// Entry point to crate resolution. + pub fn resolve_crate(&mut self, krate: &Crate) { + // Currently, we ignore the name resolution data structures for + // the purposes of dependency tracking. Instead we will run name + // resolution and include its output in the hash of each item, + // much like we do for macro expansion. In other words, the hash + // reflects not just its contents but the results of name + // resolution on those contents. Hopefully we'll push this back at + // some point. + let _ignore = self.session.dep_graph.in_ignore(); + + self.build_reduced_graph(krate); + resolve_imports::resolve_imports(self); + + self.current_module = self.graph_root; + visit::walk_crate(self, krate); + + check_unused::check_crate(self, krate); + self.report_privacy_errors(); + } + fn new_module(&self, parent_link: ParentLink<'a>, def: Option, external: bool) -> Module<'a> { self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas)) @@ -1568,12 +1586,6 @@ fn search_label(&self, name: Name) -> Option { None } - fn resolve_crate(&mut self, krate: &Crate) { - debug!("(resolving crate) starting"); - self.current_module = self.graph_root; - visit::walk_crate(self, krate); - } - fn resolve_item(&mut self, item: &Item) { let name = item.ident.name; @@ -2287,24 +2299,25 @@ fn resolve_pattern(&mut self, PatKind::Ident(bmode, ref ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let resolution = if let Ok(resolution) = self.resolve_path(pat.id, - &Path::from_ident(ident.span, ident.node), 0, ValueNS) { + let local_def = self.resolve_identifier(ident.node, ValueNS, true); + let resolution = if let Some(LocalDef { def, .. }) = local_def { let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || bmode != BindingMode::ByValue(Mutability::Immutable); - match resolution.base_def { + match def { Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { // A constant, unit variant, etc pattern. - resolution + PathResolution::new(def) } Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { // A fresh binding that shadows something unacceptable. + let kind_name = PathResolution::new(def).kind_name(); resolve_error( self, ident.span, ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), resolution.kind_name(), ident.node.name) + pat_src.descr(), kind_name, ident.node.name) ); err_path_resolution() } @@ -3194,7 +3207,9 @@ fn lookup_candidates(&mut self, if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { // add the module to the lookup let is_extern = in_module_is_extern || name_binding.is_extern_crate(); - worklist.push((module, path_segments, is_extern)); + if !worklist.iter().any(|&(m, _, _)| m.def == module.def) { + worklist.push((module, path_segments, is_extern)); + } } } }) @@ -3454,34 +3469,4 @@ pub enum MakeGlobMap { No, } -/// Entry point to crate resolution. -pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) { - // Currently, we ignore the name resolution data structures for - // the purposes of dependency tracking. Instead we will run name - // resolution and include its output in the hash of each item, - // much like we do for macro expansion. In other words, the hash - // reflects not just its contents but the results of name - // resolution on those contents. Hopefully we'll push this back at - // some point. - let _ignore = resolver.session.dep_graph.in_ignore(); - - resolver.build_reduced_graph(krate); - resolve_imports::resolve_imports(resolver); - resolver.resolve_crate(krate); - - check_unused::check_crate(resolver, krate); - resolver.report_privacy_errors(); -} - -pub fn with_resolver<'a, T, F>(session: &'a Session, - definitions: &'a mut Definitions, - make_glob_map: MakeGlobMap, - f: F) -> T - where F: for<'b> FnOnce(Resolver<'b>) -> T, -{ - let arenas = Resolver::arenas(); - let resolver = Resolver::new(session, definitions, make_glob_map, &arenas); - f(resolver) -} - __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f63d37b3403..48acf31b993 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1696,6 +1696,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, document(w, cx, item)?; let mut indices = (0..items.len()).filter(|i| { + if let clean::DefaultImplItem(..) = items[*i].inner { + return false; + } !cx.maybe_ignore_item(&items[*i]) }).collect::>(); diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 1980d1f9cc4..b8e40790646 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -12,6 +12,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::util::nodemap::DefIdSet; use std::cmp; +use std::mem; use std::string::String; use std::usize; @@ -29,7 +30,8 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { // strip all #[doc(hidden)] items let krate = { struct Stripper<'a> { - retained: &'a mut DefIdSet + retained: &'a mut DefIdSet, + update_retained: bool, } impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { @@ -38,17 +40,25 @@ fn fold_item(&mut self, i: Item) -> Option { // use a dedicated hidden item for given item type if any match i.inner { clean::StructFieldItem(..) | clean::ModuleItem(..) => { - return Strip(i).fold() + // We need to recurse into stripped modules to + // strip things like impl methods but when doing so + // we must not add any items to the `retained` set. + let old = mem::replace(&mut self.update_retained, false); + let ret = Strip(self.fold_item_recur(i).unwrap()).fold(); + self.update_retained = old; + return ret; } _ => return None, } } else { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } } self.fold_item_recur(i) } } - let mut stripper = Stripper{ retained: &mut retained }; + let mut stripper = Stripper{ retained: &mut retained, update_retained: true }; stripper.fold_crate(krate) }; @@ -69,6 +79,7 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult { let mut stripper = Stripper { retained: &mut retained, access_levels: &access_levels, + update_retained: true, }; krate = ImportStripper.fold_crate(stripper.fold_crate(krate)); } @@ -81,12 +92,21 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult { struct Stripper<'a> { retained: &'a mut DefIdSet, access_levels: &'a AccessLevels, + update_retained: bool, } impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { match i.inner { - clean::StrippedItem(..) => return Some(i), + clean::StrippedItem(..) => { + // We need to recurse into stripped modules to strip things + // like impl methods but when doing so we must not add any + // items to the `retained` set. + let old = mem::replace(&mut self.update_retained, false); + let ret = self.fold_item_recur(i); + self.update_retained = old; + return ret; + } // These items can all get re-exported clean::TypedefItem(..) | clean::StaticItem(..) | clean::StructItem(..) | clean::EnumItem(..) | @@ -109,18 +129,13 @@ fn fold_item(&mut self, i: Item) -> Option { clean::ModuleItem(..) => { if i.def_id.is_local() && i.visibility != Some(clean::Public) { - return Strip(self.fold_item_recur(i).unwrap()).fold() + let old = mem::replace(&mut self.update_retained, false); + let ret = Strip(self.fold_item_recur(i).unwrap()).fold(); + self.update_retained = old; + return ret; } } - // trait impls for private items should be stripped - clean::ImplItem(clean::Impl{ - for_: clean::ResolvedPath{ did, is_generic, .. }, .. - }) => { - if did.is_local() && !is_generic && !self.access_levels.is_exported(did) { - return None; - } - } // handled in the `strip-priv-imports` pass clean::ExternCrateItem(..) | clean::ImportItem(..) => {} @@ -152,7 +167,9 @@ fn fold_item(&mut self, i: Item) -> Option { }; let i = if fastreturn { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } return Some(i); } else { self.fold_item_recur(i) @@ -160,13 +177,14 @@ fn fold_item(&mut self, i: Item) -> Option { i.and_then(|i| { match i.inner { - // emptied modules/impls have no need to exist + // emptied modules have no need to exist clean::ModuleItem(ref m) if m.items.is_empty() && i.doc_value().is_none() => None, - clean::ImplItem(ref i) if i.items.is_empty() => None, _ => { - self.retained.insert(i.def_id); + if self.update_retained { + self.retained.insert(i.def_id); + } Some(i) } } @@ -182,6 +200,10 @@ struct ImplStripper<'a> { impl<'a> fold::DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = i.inner { + // emptied none trait impls can be stripped + if imp.trait_.is_none() && imp.items.is_empty() { + return None; + } if let Some(did) = imp.for_.def_id() { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a352715b20b..cc033cec8b8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -19,7 +19,6 @@ use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use codemap::{respan, Spanned}; use abi::Abi; -use errors; use parse::token::{self, keywords, InternedString}; use print::pprust; use ptr::P; @@ -362,15 +361,6 @@ pub struct ParenthesizedParameterData { /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = !0; -pub trait NodeIdAssigner { - fn next_node_id(&self) -> NodeId; - fn peek_node_id(&self) -> NodeId; - - fn diagnostic(&self) -> &errors::Handler { - panic!("this ID assigner cannot emit diagnostics") - } -} - /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index da2967e306f..3c88fb8f670 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -839,7 +839,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match *self { StmtKind::Local(ref local) => local.attrs(), - StmtKind::Item(ref item) => item.attrs(), + StmtKind::Item(..) => &[], StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), StmtKind::Mac(ref mac) => { let (_, _, ref attrs) = **mac; @@ -851,7 +851,7 @@ fn attrs(&self) -> &[Attribute] { fn map_attrs) -> Vec>(self, f: F) -> Self { match self { StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)), - StmtKind::Item(item) => StmtKind::Item(item.map_attrs(f)), + StmtKind::Item(..) => self, StmtKind::Expr(expr) => StmtKind::Expr(expr.map_attrs(f)), StmtKind::Semi(expr) => StmtKind::Semi(expr.map_attrs(f)), StmtKind::Mac(mac) => StmtKind::Mac(mac.map(|(mac, style, attrs)| { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 961763c6025..eaf82f5f43d 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -213,12 +213,7 @@ fn fold_opt_expr(&mut self, expr: P) -> Option> { } fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { - // avoid calling `visit_stmt_or_expr_attrs` on items - match stmt.node { - ast::StmtKind::Item(_) => {} - _ => self.visit_stmt_or_expr_attrs(stmt.attrs()), - } - + self.visit_stmt_or_expr_attrs(stmt.attrs()); self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self)) .unwrap_or(SmallVector::zero()) } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 757b039fcac..ca38ef068d0 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -443,6 +443,10 @@ fn make_stmts(self: Box) -> Option> { span: self.span, })) } + + fn make_ty(self: Box) -> Option> { + Some(DummyResult::raw_ty(self.span)) + } } /// An enum representing the different kinds of syntax extensions. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3036a88430a..c670283e559 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -43,18 +43,19 @@ trait MacroGenerable: Sized { fn fold_with(self, folder: &mut F) -> Self; fn visit_with(&self, visitor: &mut V); - // Return a placeholder expansion to allow compilation to continue after an erroring expansion. - fn dummy(span: Span) -> Self; - // The user-friendly name of the node type (e.g. "expression", "item", etc.) for diagnostics. fn kind_name() -> &'static str; + + // Return a placeholder expansion to allow compilation to continue after an erroring expansion. + fn dummy(span: Span) -> Self { + Self::make_with(DummyResult::any(span)).unwrap() + } } macro_rules! impl_macro_generable { ($($ty:ty: $kind_name:expr, .$make:ident, $(.$fold:ident)* $(lift .$fold_elt:ident)*, - $(.$visit:ident)* $(lift .$visit_elt:ident)*, - |$span:ident| $dummy:expr;)*) => { $( + $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { $( impl MacroGenerable for $ty { fn kind_name() -> &'static str { $kind_name } fn make_with<'a>(result: Box) -> Option { result.$make() } @@ -66,31 +67,24 @@ fn visit_with(&self, visitor: &mut V) { $( visitor.$visit(self) )* $( for item in self.as_slice() { visitor. $visit_elt (item) } )* } - fn dummy($span: Span) -> Self { $dummy } } )* } } impl_macro_generable! { - P: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span)); - P: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span); - P: - "expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span); - SmallVector: - "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero(); - SmallVector>: - "item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero(); + P: "expression", .make_expr, .fold_expr, .visit_expr; + P: "pattern", .make_pat, .fold_pat, .visit_pat; + P: "type", .make_ty, .fold_ty, .visit_ty; + SmallVector: "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt; + SmallVector>: "item", .make_items, lift .fold_item, lift .visit_item; SmallVector: - "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item, - |_span| SmallVector::zero(); + "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item; SmallVector: - "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item, - |_span| SmallVector::zero(); + "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item; } impl MacroGenerable for Option> { fn kind_name() -> &'static str { "expression" } - fn dummy(_span: Span) -> Self { None } fn make_with<'a>(result: Box) -> Option { result.make_expr().map(Some) } @@ -208,7 +202,7 @@ fn mac_result<'a>(path: &ast::Path, ident: Option, tts: Vec, m &fld.cx.ecfg.features.unwrap()); } - if path.segments.len() > 1 { + if path.segments.len() > 1 || path.global || !path.segments[0].parameters.is_empty() { fld.cx.span_err(path.span, "expected macro name without module separators"); return None; } @@ -691,7 +685,7 @@ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { } fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector { - let new_items: SmallVector = match a { + match a { Annotatable::Item(it) => match it.node { ast::ItemKind::Mac(..) => { it.and_then(|it| match it.node { @@ -728,63 +722,6 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector expand_impl_item(ii.unwrap(), fld).into_iter(). map(|ii| Annotatable::ImplItem(P(ii))).collect() } - }; - - new_items.into_iter().flat_map(|a| decorate(a, fld)).collect() -} - -fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector { - let mut decorator_items = SmallVector::zero(); - let mut new_attrs = Vec::new(); - expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs); - - let mut new_items = SmallVector::one(a.fold_attrs(new_attrs)); - new_items.push_all(decorator_items); - new_items -} - -fn expand_decorators(a: Annotatable, - fld: &mut MacroExpander, - decorator_items: &mut SmallVector, - new_attrs: &mut Vec) -{ - for attr in a.attrs() { - let mname = intern(&attr.name()); - match fld.cx.syntax_env.find(mname) { - Some(rc) => match *rc { - MultiDecorator(ref dec) => { - attr::mark_used(&attr); - - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - format: MacroAttribute(mname), - span: Some(attr.span), - // attributes can do whatever they like, - // for now. - allow_internal_unstable: true, - } - }); - - let mut items: SmallVector = SmallVector::zero(); - dec.expand(fld.cx, - attr.span, - &attr.node.value, - &a, - &mut |ann| items.push(ann)); - - for item in items { - for configured_item in item.fold_with(&mut fld.strip_unconfigured()) { - decorator_items.extend(expand_annotatable(configured_item, fld)); - } - } - - fld.cx.bt_pop(); - } - _ => new_attrs.push((*attr).clone()), - }, - _ => new_attrs.push((*attr).clone()), - } } } @@ -793,9 +730,12 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe item = item.map_attrs(|mut attrs| { for i in 0..attrs.len() { if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) { - if let MultiModifier(..) = *extension { - multi_modifier = Some((attrs.remove(i), extension)); - break; + match *extension { + MultiModifier(..) | MultiDecorator(..) => { + multi_modifier = Some((attrs.remove(i), extension)); + break; + } + _ => {} } } } @@ -804,23 +744,32 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe match multi_modifier { None => expand_multi_modified(item, fld), - Some((attr, extension)) => match *extension { - MultiModifier(ref mac) => { - attr::mark_used(&attr); - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - format: MacroAttribute(intern(&attr.name())), - span: Some(attr.span), - // attributes can do whatever they like, for now - allow_internal_unstable: true, - } - }); - let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item); - fld.cx.bt_pop(); - modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect() - } - _ => unreachable!(), + Some((attr, extension)) => { + attr::mark_used(&attr); + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + format: MacroAttribute(intern(&attr.name())), + span: Some(attr.span), + // attributes can do whatever they like, for now + allow_internal_unstable: true, + } + }); + + let modified = match *extension { + MultiModifier(ref mac) => mac.expand(fld.cx, attr.span, &attr.node.value, item), + MultiDecorator(ref mac) => { + let mut items = Vec::new(); + mac.expand(fld.cx, attr.span, &attr.node.value, &item, + &mut |item| items.push(item)); + items.push(item); + items + } + _ => unreachable!(), + }; + + fld.cx.bt_pop(); + modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect() } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6789e7be058..ed6f09eed64 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1102,7 +1102,6 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr { Expr { - id: folder.new_id(id), node: match node { ExprKind::Box(e) => { ExprKind::Box(folder.fold_expr(e)) @@ -1270,9 +1269,19 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu fields.move_map(|x| folder.fold_field(x)), maybe_expr.map(|x| folder.fold_expr(x))) }, - ExprKind::Paren(ex) => ExprKind::Paren(folder.fold_expr(ex)), + ExprKind::Paren(ex) => { + let sub_expr = folder.fold_expr(ex); + return Expr { + // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids. + id: sub_expr.id, + node: ExprKind::Paren(sub_expr), + span: folder.new_span(span), + attrs: fold_attrs(attrs.into(), folder).into(), + }; + } ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), }, + id: folder.new_id(id), span: folder.new_span(span), attrs: fold_attrs(attrs.into(), folder).into(), } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 813d90103b8..20a54228d01 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -553,10 +553,6 @@ pub fn commit_stmt(&mut self, edible: &[token::Token], self.expect_one_of(edible, inedible) } - pub fn commit_stmt_expecting(&mut self, edible: token::Token) -> PResult<'a, ()> { - self.commit_stmt(&[edible], &[]) - } - /// returns the span of expr, if it was not interpolated or the span of the interpolated token fn interpolated_or_expr_span(&self, expr: PResult<'a, P>) @@ -4122,7 +4118,7 @@ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P< _ => { // all other kinds of statements: let mut hi = span.hi; if classify::stmt_ends_with_semi(&node) { - self.commit_stmt_expecting(token::Semi)?; + self.commit_stmt(&[token::Semi], &[])?; hi = self.last_span.hi; } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 647e414a7fd..e01f4ed1f9b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -345,15 +345,18 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter ``, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. -fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec> { +fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt) + -> Vec> { use syntax::visit; - struct Visitor<'a> { + struct Visitor<'a, 'b: 'a> { + cx: &'a ExtCtxt<'b>, + span: Span, ty_param_names: &'a [ast::Name], types: Vec>, } - impl<'a> visit::Visitor for Visitor<'a> { + impl<'a, 'b> visit::Visitor for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &ast::Ty) { match ty.node { ast::TyKind::Path(_, ref path) if !path.global => { @@ -371,11 +374,18 @@ fn visit_ty(&mut self, ty: &ast::Ty) { visit::walk_ty(self, ty) } + + fn visit_mac(&mut self, mac: &ast::Mac) { + let span = Span { expn_id: self.span.expn_id, ..mac.span }; + self.cx.span_err(span, "`derive` cannot be used on items with type macros"); + } } let mut visitor = Visitor { ty_param_names: ty_param_names, types: Vec::new(), + span: span, + cx: cx, }; visit::Visitor::visit_ty(&mut visitor, ty); @@ -556,7 +566,7 @@ fn create_derived_impl(&self, let mut processed_field_types = HashSet::new(); for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names); + let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); for ty in tys { // if we have already handled this type, skip it diff --git a/src/test/compile-fail/auxiliary/recursive_reexports.rs b/src/test/compile-fail/auxiliary/recursive_reexports.rs new file mode 100644 index 00000000000..1186e3d62f7 --- /dev/null +++ b/src/test/compile-fail/auxiliary/recursive_reexports.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod foo { + pub use foo; +} diff --git a/src/test/compile-fail/issue-32950.rs b/src/test/compile-fail/issue-32950.rs index e47ebdd6a69..e8ca1c1fa98 100644 --- a/src/test/compile-fail/issue-32950.rs +++ b/src/test/compile-fail/issue-32950.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(type_macros, concat_idents, rustc_attrs)] -#![allow(unused)] +#![feature(type_macros, concat_idents)] -#[derive(Debug)] struct FooBar; -#[derive(Debug)] struct Baz(T, concat_idents!(Foo, Bar)); +#[derive(Debug)] //~ NOTE in this expansion +struct Baz( + concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros +); -#[rustc_error] -fn main() {} //~ ERROR compilation successful +fn main() {} diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs index 9499d732a38..e99dfb9aa0f 100644 --- a/src/test/compile-fail/lint-type-overflow2.rs +++ b/src/test/compile-fail/lint-type-overflow2.rs @@ -15,6 +15,7 @@ #[allow(unused_variables)] fn main() { let x2: i8 = --128; //~ error: literal out of range for i8 + //~^ error: attempted to negate with overflow let x = -3.40282348e+38_f32; //~ error: literal out of range for f32 let x = 3.40282348e+38_f32; //~ error: literal out of range for f32 diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs index 95250e36b86..408bb15ba28 100644 --- a/src/test/compile-fail/macro-with-seps-err-msg.rs +++ b/src/test/compile-fail/macro-with-seps-err-msg.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected macro name without module separators - fn main() { - globnar::brotz!(); + globnar::brotz!(); //~ ERROR expected macro name without module separators + ::foo!(); //~ ERROR expected macro name without module separators + foo::!(); //~ ERROR expected macro name without module separators } diff --git a/src/test/compile-fail/recursive-reexports.rs b/src/test/compile-fail/recursive-reexports.rs new file mode 100644 index 00000000000..6fd52beeec6 --- /dev/null +++ b/src/test/compile-fail/recursive-reexports.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:recursive_reexports.rs + +fn f() -> recursive_reexports::S {} //~ ERROR undeclared + +fn main() {} diff --git a/src/test/parse-fail/issue-33455.rs b/src/test/parse-fail/issue-33455.rs new file mode 100644 index 00000000000..96070332f06 --- /dev/null +++ b/src/test/parse-fail/issue-33455.rs @@ -0,0 +1,11 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use foo.bar; //~ ERROR expected one of `::`, `;`, or `as`, found `.` diff --git a/src/test/rustdoc/hidden-impls.rs b/src/test/rustdoc/hidden-impls.rs new file mode 100644 index 00000000000..203c56e9e2e --- /dev/null +++ b/src/test/rustdoc/hidden-impls.rs @@ -0,0 +1,27 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +mod hidden { + #[derive(Clone)] + pub struct Foo; +} + +#[doc(hidden)] +pub mod __hidden { + pub use hidden::Foo; +} + +// @has foo/trait.Clone.html +// @!has - 'Foo' +// @has implementors/foo/trait.Clone.js +// @!has - 'Foo' +pub use std::clone::Clone; diff --git a/src/test/rustdoc/hidden-methods.rs b/src/test/rustdoc/hidden-methods.rs new file mode 100644 index 00000000000..18f5f086cd1 --- /dev/null +++ b/src/test/rustdoc/hidden-methods.rs @@ -0,0 +1,39 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +#[doc(hidden)] +pub mod hidden { + pub struct Foo; + + impl Foo { + #[doc(hidden)] + pub fn this_should_be_hidden() {} + } + + pub struct Bar; + + impl Bar { + fn this_should_be_hidden() {} + } +} + +// @has foo/struct.Foo.html +// @!has - 'Methods' +// @!has - 'impl Foo' +// @!has - 'this_should_be_hidden' +pub use hidden::Foo; + +// @has foo/struct.Bar.html +// @!has - 'Methods' +// @!has - 'impl Bar' +// @!has - 'this_should_be_hidden' +pub use hidden::Bar; diff --git a/src/test/rustdoc/module-impls.rs b/src/test/rustdoc/module-impls.rs new file mode 100644 index 00000000000..7be3c500731 --- /dev/null +++ b/src/test/rustdoc/module-impls.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +pub use std::marker::Send; + +// @!has foo/index.html 'Implementations' diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index cc687b53204..6830f32bb2c 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -254,6 +254,17 @@ pub fn run_tests(config: &Config) { match config.mode { DebugInfoLldb => { + if let Some(lldb_version) = config.lldb_version.as_ref() { + if is_blacklisted_lldb_version(&lldb_version[..]) { + println!("WARNING: The used version of LLDB ({}) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + lldb_version); + return + } + } + // Some older versions of LLDB seem to have problems with multiple // instances running in parallel, so only run one test thread at a // time. @@ -524,3 +535,7 @@ fn extract_lldb_version(full_version_line: Option) -> Option { } None } + +fn is_blacklisted_lldb_version(version: &str) -> bool { + version == "350" +}