fi
if [ "$t" != "$CFG_BUILD" ]; then
+ # see http://llvm.org/docs/HowToCrossCompileLLVM.html
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CROSSCOMPILING=True"
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGET_ARCH=$arch"
- CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TABLEGEN=$LLVM_INST_DIR/bin/llvm-tablegen"
+ CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TABLEGEN=$CFG_BUILD_DIR/$CFG_BUILD/llvm/bin/llvm-tblgen"
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_DEFAULT_TARGET_TRIPLE=$t"
fi
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;
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.
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
} 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,
}
}
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 {
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");
}
_ => {}
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")),
};
}
// 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<DefIndex>,
}
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);
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,
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;
}
}
+ 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()
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::*;
}
}
-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> {
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,
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;
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
}
}
}
-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<String> {
// Conditions for enabling multi-line errors:
if !msg.contains("mismatched types") &&
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),
// 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;
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;
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;
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> {
after_hir_lowering: PhaseController::basic(),
after_analysis: PhaseController::basic(),
after_llvm: PhaseController::basic(),
- make_glob_map: resolve::MakeGlobMap::No,
+ make_glob_map: MakeGlobMap::No,
}
}
}
mut krate: ast::Crate,
crate_name: &'a str,
addl_plugins: Option<Vec<String>>,
- make_glob_map: resolve::MakeGlobMap)
+ make_glob_map: MakeGlobMap)
-> Result<ExpansionResult<'a>, usize> {
let time_passes = sess.time_passes();
krate = assign_node_ids(sess, krate);
+ let resolver_arenas = Resolver::arenas();
+ let mut resolver = Resolver::new(sess, make_glob_map, &resolver_arenas);
+
// Collect defintions for def ids.
- let mut defs =
- time(sess.time_passes(), "collecting defs", || hir_map::collect_definitions(&krate));
+ time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate));
- time(sess.time_passes(),
- "external crate/lib resolution",
- || read_local_crates(sess, &cstore, &defs, &krate, crate_name, &sess.dep_graph));
+ 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",
"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) {
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
})
}
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.
use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast;
-use syntax::ast::NodeIdAssigner;
use syntax::ptr::P;
use syntax_pos;
#[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};
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()
#[cfg(test)]
fn with_testing_context<T, F: FnOnce(&mut LoweringContext) -> 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)
}
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.
"##,
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.
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
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 {}
}
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();
}
use foo::MyTrait::do_something;
+
+fn main() {}
```
It's invalid to directly import methods belonging to a trait or concrete type.
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() {}
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.
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
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;
"##,
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 {
}
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
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
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<T>(x: T) {
fn bar(y: T) { // T is defined in the "outer" function
// ..
Nor will this:
-```compile_fail
+```compile_fail,E0401
fn foo<T>(x: T) {
type MaybeT = Option<T>;
// ...
Or this:
-```compile_fail
+```compile_fail,E0401
fn foo<T>(x: T) {
struct Foo {
x: 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<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
// parameter in this type parameter list
```
"##,
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;
"##,
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
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();
}
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
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
"##,
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
<Self>::foo; // error: use of `Self` outside of an impl or trait
```
"##,
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:
"##,
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
```
"##,
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
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 };
}
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 };
"##,
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();
"##,
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 {
"##,
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`
"##,
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`
}
"##,
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`
```
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
```
"##,
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
```
"##,
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
```
"##,
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`.
```
"##,
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<u32, u32> = HashMap::new(); // So it can be used!
+```
"##,
E0434: r##"
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 {
"##,
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
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 {
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 {}
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};
pub struct Resolver<'a> {
session: &'a Session,
- definitions: &'a mut Definitions,
+ pub definitions: Definitions,
graph_root: Module<'a>,
arenas: &'a ResolverArenas<'a>,
}
-struct ResolverArenas<'a> {
+pub struct ResolverArenas<'a> {
modules: arena::TypedArena<ModuleS<'a>>,
local_modules: RefCell<Vec<Module<'a>>>,
name_bindings: arena::TypedArena<NameBinding<'a>>,
}
fn definitions(&mut self) -> Option<&mut Definitions> {
- Some(self.definitions)
+ Some(&mut self.definitions)
}
}
}
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);
Resolver {
session: session,
- definitions: definitions,
+ definitions: Definitions::new(),
// The outermost module has def ID 0; this is not reflected in the
// AST.
}
}
- fn arenas() -> ResolverArenas<'a> {
+ pub fn arenas() -> ResolverArenas<'a> {
ResolverArenas {
modules: arena::TypedArena::new(),
local_modules: RefCell::new(Vec::new()),
}
}
+ /// 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<Def>, external: bool)
-> Module<'a> {
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas))
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;
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()
}
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));
+ }
}
}
})
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 }
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::<Vec<usize>>();
use rustc::middle::privacy::AccessLevels;
use rustc::util::nodemap::DefIdSet;
use std::cmp;
+use std::mem;
use std::string::String;
use std::usize;
// 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<Item> {
// 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)
};
let mut stripper = Stripper {
retained: &mut retained,
access_levels: &access_levels,
+ update_retained: true,
};
krate = ImportStripper.fold_crate(stripper.fold_crate(krate));
}
struct Stripper<'a> {
retained: &'a mut DefIdSet,
access_levels: &'a AccessLevels<DefId>,
+ update_retained: bool,
}
impl<'a> fold::DocFolder for Stripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
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(..) |
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(..) => {}
};
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)
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)
}
}
impl<'a> fold::DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
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)
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;
/// 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
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;
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(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)| {
}
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
- // 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())
}
span: self.span,
}))
}
+
+ fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
+ Some(DummyResult::raw_ty(self.span))
+ }
}
/// An enum representing the different kinds of syntax extensions.
fn fold_with<F: Folder>(self, folder: &mut F) -> Self;
fn visit_with<V: Visitor>(&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<MacResult + 'a>) -> Option<Self> { result.$make() }
$( visitor.$visit(self) )*
$( for item in self.as_slice() { visitor. $visit_elt (item) } )*
}
- fn dummy($span: Span) -> Self { $dummy }
}
)* }
}
impl_macro_generable! {
- P<ast::Pat>: "pattern", .make_pat, .fold_pat, .visit_pat, |span| P(DummyResult::raw_pat(span));
- P<ast::Ty>: "type", .make_ty, .fold_ty, .visit_ty, |span| DummyResult::raw_ty(span);
- P<ast::Expr>:
- "expression", .make_expr, .fold_expr, .visit_expr, |span| DummyResult::raw_expr(span);
- SmallVector<ast::Stmt>:
- "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero();
- SmallVector<P<ast::Item>>:
- "item", .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero();
+ P<ast::Expr>: "expression", .make_expr, .fold_expr, .visit_expr;
+ P<ast::Pat>: "pattern", .make_pat, .fold_pat, .visit_pat;
+ P<ast::Ty>: "type", .make_ty, .fold_ty, .visit_ty;
+ SmallVector<ast::Stmt>: "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
+ SmallVector<P<ast::Item>>: "item", .make_items, lift .fold_item, lift .visit_item;
SmallVector<ast::TraitItem>:
- "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<ast::ImplItem>:
- "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<P<ast::Expr>> {
fn kind_name() -> &'static str { "expression" }
- fn dummy(_span: Span) -> Self { None }
fn make_with<'a>(result: Box<MacResult + 'a>) -> Option<Self> {
result.make_expr().map(Some)
}
&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;
}
}
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
- let new_items: SmallVector<Annotatable> = match a {
+ match a {
Annotatable::Item(it) => match it.node {
ast::ItemKind::Mac(..) => {
it.and_then(|it| match it.node {
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<Annotatable> {
- 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<Annotatable>,
- new_attrs: &mut Vec<ast::Attribute>)
-{
- 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<Annotatable> = 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()),
- }
}
}
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;
+ }
+ _ => {}
}
}
}
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()
}
}
}
pub fn noop_fold_expr<T: Folder>(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))
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(),
}
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<Expr>>)
_ => { // 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;
}
/// This method helps to extract all the type parameters referenced from a
/// type. For a type parameter `<T>`, 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<P<ast::Ty>> {
+fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt)
+ -> Vec<P<ast::Ty>> {
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<P<ast::Ty>>,
}
- 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 => {
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);
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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod foo {
+ pub use foo;
+}
// 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>(T, concat_idents!(Foo, Bar));
+#[derive(Debug)] //~ NOTE in this expansion
+struct Baz<T>(
+ concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
+);
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {}
#[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
// 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::<T>!(); //~ ERROR expected macro name without module separators
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 `.`
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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'
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.
}
None
}
+
+fn is_blacklisted_lldb_version(version: &str) -> bool {
+ version == "350"
+}