]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #50016 - tmandry:cleanup-binder, r=nikomatsakis
authorbors <bors@rust-lang.org>
Wed, 25 Apr 2018 20:58:53 +0000 (20:58 +0000)
committerbors <bors@rust-lang.org>
Wed, 25 Apr 2018 20:58:53 +0000 (20:58 +0000)
Make Binder's field private and clean up its usage

AKA "tour de rustc"

Closes #49814.

44 files changed:
src/librustc/lint/builtin.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/session/mod.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/write.rs
src/libsyntax_ext/deriving/cmp/ord.rs
src/libsyntax_ext/deriving/cmp/partial_eq.rs
src/libsyntax_ext/deriving/cmp/partial_ord.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/libsyntax_ext/format.rs
src/libsyntax_pos/symbol.rs
src/test/compile-fail/array_const_index-0.rs
src/test/compile-fail/array_const_index-1.rs
src/test/compile-fail/const-err-early.rs
src/test/compile-fail/const-err-multi.rs
src/test/compile-fail/const-eval-overflow2.rs
src/test/compile-fail/const-eval-overflow2b.rs
src/test/compile-fail/const-eval-overflow2c.rs
src/test/compile-fail/const-slice-oob.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs
src/test/run-pass-fulldeps/deriving-hygiene.rs [new file with mode: 0644]
src/test/run-pass/compiletest-skip-trans.rs [new file with mode: 0644]
src/test/run-pass/format-hygiene.rs [new file with mode: 0644]
src/test/ui/const-eval/conditional_array_execution.rs
src/test/ui/const-eval/conditional_array_execution.stderr
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-eval/issue-43197.stderr
src/test/ui/const-eval/pub_const_err.rs
src/test/ui/const-eval/pub_const_err.stderr
src/test/ui/const-eval/pub_const_err_bin.rs [new file with mode: 0644]
src/test/ui/const-eval/pub_const_err_bin.stderr [new file with mode: 0644]
src/test/ui/edition-lint-paths.rs [new file with mode: 0644]
src/test/ui/edition-lint-paths.stderr [new file with mode: 0644]
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs

index 97cfcf0f60795a07080b82d196a545aee8e14db9..109edffcde38a5d3cc9a22804c6b6e3b47ed5d7f 100644 (file)
     "suggest using `dyn Trait` for trait objects"
 }
 
+declare_lint! {
+    pub ABSOLUTE_PATH_STARTING_WITH_MODULE,
+    Allow,
+    "fully qualified paths that start with a module name \
+     instead of `crate`, `self`, or an extern crate name"
+}
+
 declare_lint! {
     pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
     Warn,
@@ -314,6 +321,7 @@ fn get_lints(&self) -> LintArray {
             TYVAR_BEHIND_RAW_POINTER,
             ELIDED_LIFETIME_IN_PATH,
             BARE_TRAIT_OBJECT,
+            ABSOLUTE_PATH_STARTING_WITH_MODULE,
             UNSTABLE_NAME_COLLISION,
         )
     }
@@ -324,7 +332,8 @@ fn get_lints(&self) -> LintArray {
 #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
 pub enum BuiltinLintDiagnostics {
     Normal,
-    BareTraitObject(Span, /* is_global */ bool)
+    BareTraitObject(Span, /* is_global */ bool),
+    AbsPathWithModule(Span),
 }
 
 impl BuiltinLintDiagnostics {
@@ -339,6 +348,23 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                 };
                 db.span_suggestion(span, "use `dyn`", sugg);
             }
+            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+                let sugg = match sess.codemap().span_to_snippet(span) {
+                    Ok(ref s) => {
+                        // FIXME(Manishearth) ideally the emitting code
+                        // can tell us whether or not this is global
+                        let opt_colon = if s.trim_left().starts_with("::") {
+                            ""
+                        } else {
+                            "::"
+                        };
+
+                        format!("crate{}{}", opt_colon, s)
+                    }
+                    Err(_) => format!("crate::<path>")
+                };
+                db.span_suggestion(span, "use `crate`", sugg);
+            }
         }
     }
 }
index 11dc2a8188505119ac6a3a4d9ca58ec7ffff00ce..17c114bc3b3c0f3beff9483681aa136d30f6b221 100644 (file)
@@ -184,6 +184,7 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
                 b: hir::BodyId, s: Span, id: NodeId) {
         visit_fn(self, fk, fd, b, s, id);
     }
+
     fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); }
     fn visit_expr(&mut self, ex: &'tcx Expr) { visit_expr(self, ex); }
     fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
@@ -361,6 +362,16 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
     // swap in a new set of IR maps for this function body:
     let mut fn_maps = IrMaps::new(ir.tcx);
 
+    // Don't run unused pass for #[derive()]
+    if let FnKind::Method(..) = fk {
+        let parent = ir.tcx.hir.get_parent(id);
+        if let Some(hir::map::Node::NodeItem(i)) = ir.tcx.hir.find(parent) {
+            if i.attrs.iter().any(|a| a.check_name("automatically_derived")) {
+                return;
+            }
+        }
+    }
+
     debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);
 
     let body = ir.tcx.hir.body(body_id);
index 42483c83f4ba27f4b277133da09ba329bb7dd2ab..5f4efbeeaa8762da80ffc0cf8119189a29e418d7 100644 (file)
@@ -22,6 +22,7 @@
 
 use std::fmt;
 use std::mem;
+use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::sync::Lrc;
 use syntax::codemap;
 use syntax::ast;
@@ -677,96 +678,75 @@ pub fn nearest_common_ancestor(&self,
                                    -> Scope {
         if scope_a == scope_b { return scope_a; }
 
-        // [1] The initial values for `a_buf` and `b_buf` are not used.
-        // The `ancestors_of` function will return some prefix that
-        // is re-initialized with new values (or else fallback to a
-        // heap-allocated vector).
-        let mut a_buf: [Scope; 32] = [scope_a /* [1] */; 32];
-        let mut a_vec: Vec<Scope> = vec![];
-        let mut b_buf: [Scope; 32] = [scope_b /* [1] */; 32];
-        let mut b_vec: Vec<Scope> = vec![];
-        let parent_map = &self.parent_map;
-        let a_ancestors = ancestors_of(parent_map, scope_a, &mut a_buf, &mut a_vec);
-        let b_ancestors = ancestors_of(parent_map, scope_b, &mut b_buf, &mut b_vec);
-        let mut a_index = a_ancestors.len() - 1;
-        let mut b_index = b_ancestors.len() - 1;
-
-        // Here, [ab]_ancestors is a vector going from narrow to broad.
-        // The end of each vector will be the item where the scope is
-        // defined; if there are any common ancestors, then the tails of
-        // the vector will be the same.  So basically we want to walk
-        // backwards from the tail of each vector and find the first point
-        // where they diverge.  If one vector is a suffix of the other,
-        // then the corresponding scope is a superscope of the other.
-
-        if a_ancestors[a_index] != b_ancestors[b_index] {
-            // In this case, the two regions belong to completely
-            // different functions.  Compare those fn for lexical
-            // nesting. The reasoning behind this is subtle.  See the
-            // "Modeling closures" section of the README in
-            // infer::region_constraints for more details.
-            let a_root_scope = a_ancestors[a_index];
-            let b_root_scope = a_ancestors[a_index];
-            return match (a_root_scope.data(), b_root_scope.data()) {
-                (ScopeData::Destruction(a_root_id),
-                 ScopeData::Destruction(b_root_id)) => {
-                    if self.closure_is_enclosed_by(a_root_id, b_root_id) {
-                        // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
-                        scope_b
-                    } else if self.closure_is_enclosed_by(b_root_id, a_root_id) {
-                        // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
-                        scope_a
-                    } else {
-                        // neither fn encloses the other
-                        bug!()
-                    }
+        // Process the lists in tandem from the innermost scope, recording the
+        // scopes seen so far. The first scope that comes up for a second time
+        // is the nearest common ancestor.
+        //
+        // Note: another way to compute the nearest common ancestor is to get
+        // the full scope chain for both scopes and then compare the chains to
+        // find the first scope in a common tail. But getting a parent scope
+        // requires a hash table lookup, and we often have very long scope
+        // chains (10s or 100s of scopes) that only differ by a few elements at
+        // the start. So this algorithm is faster.
+        let mut ma = Some(scope_a);
+        let mut mb = Some(scope_b);
+        let mut seen: SmallVec<[Scope; 32]> = SmallVec::new();
+        loop {
+            if let Some(a) = ma {
+                if seen.iter().position(|s| *s == a).is_some() {
+                    return a;
                 }
-                _ => {
-                    // root ids are always Node right now
-                    bug!()
+                seen.push(a);
+                ma = self.parent_map.get(&a).map(|s| *s);
+            }
+
+            if let Some(b) = mb {
+                if seen.iter().position(|s| *s == b).is_some() {
+                    return b;
                 }
-            };
-        }
+                seen.push(b);
+                mb = self.parent_map.get(&b).map(|s| *s);
+            }
 
-        loop {
-            // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index]
-            // for all indices between a_index and the end of the array
-            if a_index == 0 { return scope_a; }
-            if b_index == 0 { return scope_b; }
-            a_index -= 1;
-            b_index -= 1;
-            if a_ancestors[a_index] != b_ancestors[b_index] {
-                return a_ancestors[a_index + 1];
+            if ma.is_none() && mb.is_none() {
+                break;
             }
-        }
+        };
 
-        fn ancestors_of<'a, 'tcx>(parent_map: &FxHashMap<Scope, Scope>,
-                                  scope: Scope,
-                                  buf: &'a mut [Scope; 32],
-                                  vec: &'a mut Vec<Scope>)
-                                  -> &'a [Scope] {
-            // debug!("ancestors_of(scope={:?})", scope);
+        fn outermost_scope(parent_map: &FxHashMap<Scope, Scope>, scope: Scope) -> Scope {
             let mut scope = scope;
-
-            let mut i = 0;
-            while i < 32 {
-                buf[i] = scope;
-                match parent_map.get(&scope) {
-                    Some(&superscope) => scope = superscope,
-                    _ => return &buf[..i+1]
-                }
-                i += 1;
+            loop {
+               match parent_map.get(&scope) {
+                   Some(&superscope) => scope = superscope,
+                   None => break scope,
+               }
             }
+        }
 
-            *vec = Vec::with_capacity(64);
-            vec.extend_from_slice(buf);
-            loop {
-                vec.push(scope);
-                match parent_map.get(&scope) {
-                    Some(&superscope) => scope = superscope,
-                    _ => return &*vec
+        // In this (rare) case, the two regions belong to completely different
+        // functions. Compare those fn for lexical nesting. The reasoning
+        // behind this is subtle. See the "Modeling closures" section of the
+        // README in infer::region_constraints for more details.
+        let a_root_scope = outermost_scope(&self.parent_map, scope_a);
+        let b_root_scope = outermost_scope(&self.parent_map, scope_b);
+        match (a_root_scope.data(), b_root_scope.data()) {
+            (ScopeData::Destruction(a_root_id),
+             ScopeData::Destruction(b_root_id)) => {
+                if self.closure_is_enclosed_by(a_root_id, b_root_id) {
+                    // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
+                    scope_b
+                } else if self.closure_is_enclosed_by(b_root_id, a_root_id) {
+                    // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
+                    scope_a
+                } else {
+                    // neither fn encloses the other
+                    bug!()
                 }
             }
+            _ => {
+                // root ids are always Node right now
+                bug!()
+            }
         }
     }
 
index 5e4dee7fb60ca64bb54cde363b561a1d6431eede..3bd2bb3c8beb0d10bfdde8b60fd2246e0acba3c9 100644 (file)
@@ -156,7 +156,7 @@ pub struct Session {
 
     /// Loaded up early on in the initialization of this `Session` to avoid
     /// false positives about a job server in our environment.
-    pub jobserver_from_env: Option<Client>,
+    pub jobserver: Client,
 
     /// Metadata about the allocators for the current crate being compiled
     pub has_global_allocator: Once<bool>,
@@ -1128,14 +1128,23 @@ pub fn build_session_(
         // positives, or in other words we try to execute this before we open
         // any file descriptors ourselves.
         //
+        // Pick a "reasonable maximum" if we don't otherwise have
+        // a jobserver in our environment, capping out at 32 so we
+        // don't take everything down by hogging the process run queue.
+        // The fixed number is used to have deterministic compilation
+        // across machines.
+        //
         // Also note that we stick this in a global because there could be
         // multiple `Session` instances in this process, and the jobserver is
         // per-process.
-        jobserver_from_env: unsafe {
-            static mut GLOBAL_JOBSERVER: *mut Option<Client> = 0 as *mut _;
+        jobserver: unsafe {
+            static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _;
             static INIT: std::sync::Once = std::sync::ONCE_INIT;
             INIT.call_once(|| {
-                GLOBAL_JOBSERVER = Box::into_raw(Box::new(Client::from_env()));
+                let client = Client::from_env().unwrap_or_else(|| {
+                    Client::new(32).expect("failed to create jobserver")
+                });
+                GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));
             });
             (*GLOBAL_JOBSERVER).clone()
         },
index 141d491327aa4544af0c4419df8f8a0bd677a340..76991e3e52d57a58c44022e68b374f9b4c6a271a 100644 (file)
@@ -1441,3 +1441,71 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         }
     }
 }
+
+/// Lint constants that are erroneous.
+/// Without this lint, we might not get any diagnostic if the constant is
+/// unused within this crate, even though downstream crates can't use it
+/// without producing an error.
+pub struct UnusedBrokenConst;
+
+impl LintPass for UnusedBrokenConst {
+    fn get_lints(&self) -> LintArray {
+        lint_array!()
+    }
+}
+
+fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
+    let def_id = cx.tcx.hir.body_owner_def_id(body_id);
+    let param_env = cx.tcx.param_env(def_id);
+    let cid = ::rustc::mir::interpret::GlobalId {
+        instance: ty::Instance::mono(cx.tcx, def_id),
+        promoted: None
+    };
+    if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
+        let span = cx.tcx.def_span(def_id);
+        let mut diag = cx.struct_span_lint(
+            CONST_ERR,
+            span,
+            &format!("this {} cannot be used", what),
+        );
+        use rustc::middle::const_val::ConstEvalErrDescription;
+        match err.description() {
+            ConstEvalErrDescription::Simple(message) => {
+                diag.span_label(span, message);
+            }
+            ConstEvalErrDescription::Backtrace(miri, frames) => {
+                diag.span_label(span, format!("{}", miri));
+                for frame in frames {
+                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
+                }
+            }
+        }
+        diag.emit()
+    }
+}
+
+struct UnusedBrokenConstVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
+
+impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UnusedBrokenConstVisitor<'a, 'tcx> {
+    fn visit_nested_body(&mut self, id: hir::BodyId) {
+        check_const(self.0, id, "array length");
+    }
+    fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match it.node {
+            hir::ItemConst(_, body_id) => {
+                check_const(cx, body_id, "constant");
+            },
+            hir::ItemTy(ref ty, _) => hir::intravisit::walk_ty(
+                &mut UnusedBrokenConstVisitor(cx),
+                ty
+            ),
+            _ => {},
+        }
+    }
+}
index 16e8600f2d89bfec62c9bb5eeccdcec779c850fb..889c7d3e34ef96c45d93f3bda047037a3df98dcc 100644 (file)
@@ -40,7 +40,7 @@
 extern crate syntax_pos;
 
 use rustc::lint;
-use rustc::lint::builtin::BARE_TRAIT_OBJECT;
+use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE};
 use rustc::session;
 use rustc::util;
 
@@ -136,6 +136,7 @@ macro_rules! add_lint_group {
                  UnionsWithDropFields,
                  UnreachablePub,
                  TypeAliasBounds,
+                 UnusedBrokenConst,
                  );
 
     add_builtin_with_new!(sess,
@@ -278,6 +279,11 @@ macro_rules! add_lint_group {
             // Note: this item represents future incompatibility of all unstable functions in the
             //       standard library, and thus should never be removed or changed to an error.
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE),
+            reference: "issue TBD",
+            edition: Some(Edition::Edition2018),
+        },
         ]);
 
     // Register renamed and removed lints
index 671856c4e549e34507dc8dbf18d5eaaf83a50e30..7a87a72afc294635476d2041b5761213d4b3e769 100644 (file)
@@ -1654,11 +1654,12 @@ fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error
         let path: Vec<Ident> = segments.iter()
             .map(|seg| Ident::new(seg.name, span))
             .collect();
-        match self.resolve_path(&path, Some(namespace), true, span) {
+        // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
+        match self.resolve_path(&path, Some(namespace), true, span, None) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
-            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span, None) {
                 PathResult::Failed(span, msg, _) => {
                     error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -2360,7 +2361,8 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
             if def != Def::Err {
                 new_id = Some(def.def_id());
                 let span = trait_ref.path.span;
-                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) {
+                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span,
+                                                                      Some(trait_ref.ref_id)) {
                     new_val = Some((module, trait_ref.clone()));
                 }
             }
@@ -2819,7 +2821,8 @@ fn smart_resolve_path_fragment(&mut self,
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
-                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
+                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
+                                                             false, span, None) {
                         PathResult::Module(module) => module.def(),
                         _ => None,
                     }.map_or(format!(""), |def| format!("{} ", def.kind_name()));
@@ -3149,7 +3152,7 @@ fn resolve_qpath(&mut self,
             ));
         }
 
-        let result = match self.resolve_path(&path, Some(ns), true, span) {
+        let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
@@ -3186,7 +3189,7 @@ fn resolve_qpath(&mut self,
            path[0].name != keywords::CrateRoot.name() &&
            path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
-                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
+                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
@@ -3205,7 +3208,9 @@ fn resolve_path(&mut self,
                     path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
-                    path_span: Span)
+                    path_span: Span,
+                    node_id: Option<NodeId>) // None indicates that we don't care about linting
+                                             // `::module` paths
                     -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
@@ -3253,6 +3258,8 @@ fn resolve_path(&mut self,
                     let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
+                       // Note: When this feature stabilizes, this should
+                       // be gated on sess.rust_2018()
                        self.session.features_untracked().extern_absolute_paths {
                         // `::extern_crate::a::b`
                         let crate_id = self.crate_loader.process_path_extern(name, ident.span);
@@ -3324,6 +3331,33 @@ fn resolve_path(&mut self,
                                                   format!("Not a module `{}`", ident),
                                                   is_last);
                     }
+
+                    if let Some(id) = node_id {
+                        if i == 1 && self.session.features_untracked().crate_in_paths
+                                  && !self.session.rust_2018() {
+                            let prev_name = path[0].name;
+                            if prev_name == keywords::Extern.name() ||
+                               prev_name == keywords::CrateRoot.name() {
+                                let mut is_crate = false;
+                                if let NameBindingKind::Import { directive: d, .. } = binding.kind {
+                                    if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
+                                        is_crate = true;
+                                    }
+                                }
+
+                                if !is_crate {
+                                    let diag = lint::builtin::BuiltinLintDiagnostics
+                                                   ::AbsPathWithModule(path_span);
+                                    self.session.buffer_lint_with_diagnostic(
+                                        lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE,
+                                        id, path_span,
+                                        "Absolute paths must start with `self`, `super`, \
+                                        `crate`, or an external crate name in the 2018 edition",
+                                        diag);
+                                }
+                            }
+                        }
+                    }
                 }
                 Err(Undetermined) => return PathResult::Indeterminate,
                 Err(Determined) => {
@@ -3571,7 +3605,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
             // Search in module.
             let mod_path = &path[..path.len() - 1];
             if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
-                                                                  false, span) {
+                                                                  false, span, None) {
                 add_module_candidates(module, &mut names);
             }
         }
index 3a859c02c16c433629c8c6acfac5eeff40effa1e..af1e17cd89c090ee903ac95094a8ee4f96e8caa6 100644 (file)
@@ -438,7 +438,7 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
+            let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => {
@@ -616,7 +616,7 @@ pub fn resolve_legacy_scope(&mut self,
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(&path, Some(MacroNS), true, span) {
+            match self.resolve_path(&path, Some(MacroNS), true, span, None) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
index 37c62a7b0b45b276ab49270c3987195583e32123..e2a7f5668d251b535cdf50f152441328a2b16b4f 100644 (file)
@@ -535,7 +535,8 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
-            let result = self.resolve_path(&directive.module_path[..], None, false, directive.span);
+            let result = self.resolve_path(&directive.module_path[..], None, false,
+                                           directive.span, Some(directive.id));
             directive.vis.set(vis);
 
             match result {
@@ -663,7 +664,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
             }
         }
 
-        let module_result = self.resolve_path(&module_path, None, true, span);
+        let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id));
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(span, msg, false) => {
@@ -677,7 +678,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 if !self_path.is_empty() && !is_special(self_path[0]) &&
                    !(self_path.len() > 1 && is_special(self_path[1])) {
                     self_path[0].name = keywords::SelfValue.name();
-                    self_result = Some(self.resolve_path(&self_path, None, false, span));
+                    self_result = Some(self.resolve_path(&self_path, None, false,
+                                                         span, None));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))
index f501b1739eb9c6437882e1bd4d86442215364654..613a07cd2695dadf2489ad8472ba6d321167ee9e 100644 (file)
@@ -1007,13 +1007,6 @@ pub fn start_async_translation(tcx: TyCtxt,
     metadata_config.time_passes = false;
     allocator_config.time_passes = false;
 
-    let client = sess.jobserver_from_env.clone().unwrap_or_else(|| {
-        // Pick a "reasonable maximum" if we don't otherwise have a jobserver in
-        // our environment, capping out at 32 so we don't take everything down
-        // by hogging the process run queue.
-        Client::new(32).expect("failed to create jobserver")
-    });
-
     let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
     let (trans_worker_send, trans_worker_receive) = channel();
 
@@ -1023,7 +1016,7 @@ pub fn start_async_translation(tcx: TyCtxt,
                                                   trans_worker_send,
                                                   coordinator_receive,
                                                   total_cgus,
-                                                  client,
+                                                  sess.jobserver.clone(),
                                                   time_graph.clone(),
                                                   Arc::new(modules_config),
                                                   Arc::new(metadata_config),
index 1a392ac376537b40aba9cd413d6fd02c3ac5c125..99b6f752e9406a48c91e12f1ef8a806897cb9d71 100644 (file)
@@ -38,7 +38,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                           name: "cmp",
                           generics: LifetimeBounds::empty(),
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![borrowed_self()],
+                          args: vec![(borrowed_self(), "other")],
                           ret_ty: Literal(path_std!(cx, cmp::Ordering)),
                           attributes: attrs,
                           is_unsafe: false,
@@ -64,7 +64,7 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt,
 }
 
 pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-    let test_id = cx.ident_of("__cmp");
+    let test_id = cx.ident_of("cmp").gensym();
     let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
 
     let cmp_path = cx.std_path(&["cmp", "Ord", "cmp"]);
@@ -77,9 +77,9 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     // ::std::cmp::Ordering::Equal => {
     // ...
     // }
-    // __cmp => __cmp
+    // cmp => cmp
     // },
-    // __cmp => __cmp
+    // cmp => cmp
     // }
     //
     cs_fold(// foldr nests the if-elses correctly, leaving the first field
@@ -88,7 +88,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
             |cx, span, old, self_f, other_fs| {
         // match new {
         //     ::std::cmp::Ordering::Equal => old,
-        //     __cmp => __cmp
+        //     cmp => cmp
         // }
 
         let new = {
index 81ca7e732283d07b3997627013904f7b15315d57..c259733d81abdc8e8e288b3f7a91c940672b40d5 100644 (file)
@@ -78,7 +78,7 @@ macro_rules! md {
                 name: $name,
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec![borrowed_self()],
+                args: vec![(borrowed_self(), "other")],
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 is_unsafe: false,
index 9560fd0570af7b681153f91e25e10d438f12513f..d71527fd0ed0f960f11502401150d58b1575a74a 100644 (file)
@@ -34,7 +34,7 @@ macro_rules! md {
                 name: $name,
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec![borrowed_self()],
+                args: vec![(borrowed_self(), "other")],
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 is_unsafe: false,
@@ -59,7 +59,7 @@ macro_rules! md {
         name: "partial_cmp",
         generics: LifetimeBounds::empty(),
         explicit_self: borrowed_explicit_self(),
-        args: vec![borrowed_self()],
+        args: vec![(borrowed_self(), "other")],
         ret_ty,
         attributes: attrs,
         is_unsafe: false,
@@ -123,7 +123,7 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-    let test_id = cx.ident_of("__cmp");
+    let test_id = cx.ident_of("cmp").gensym();
     let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
     let ordering_expr = cx.expr_path(ordering.clone());
     let equals_expr = cx.expr_some(span, ordering_expr);
@@ -138,9 +138,9 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
     // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
     // ...
     // }
-    // __cmp => __cmp
+    // cmp => cmp
     // },
-    // __cmp => __cmp
+    // cmp => cmp
     // }
     //
     cs_fold(// foldr nests the if-elses correctly, leaving the first field
@@ -149,7 +149,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
             |cx, span, old, self_f, other_fs| {
         // match new {
         //     Some(::std::cmp::Ordering::Equal) => old,
-        //     __cmp => __cmp
+        //     cmp => cmp
         // }
 
         let new = {
index c007285cd85191afdf4eaa0037e3cd5cf7035de1..b546f5df15799467ad2daf2f8dd9408c4692a9e1 100644 (file)
@@ -40,7 +40,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
                           name: "fmt",
                           generics: LifetimeBounds::empty(),
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![fmtr],
+                          args: vec![(fmtr, "f")],
                           ret_ty: Literal(path_std!(cx, fmt::Result)),
                           attributes: Vec::new(),
                           is_unsafe: false,
@@ -70,7 +70,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = span.with_ctxt(cx.backtrace());
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str("__debug_trait_builder");
+    let builder = Ident::from_str("debug_trait_builder").gensym();
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
index 46dada256b8208c7d1f5bf2ef9f7277068e0b204..7618fe63ab3354461b499c423792defbe1f3a93b 100644 (file)
@@ -67,8 +67,8 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                                                             PathKind::Global)])],
                           },
                           explicit_self: None,
-                          args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
-                                         Borrowed(None, Mutability::Mutable))],
+                          args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
+                                         Borrowed(None, Mutability::Mutable)), "d")],
                           ret_ty:
                               Literal(Path::new_(pathvec_std!(cx, result::Result),
                                                  None,
index d579b3abd45a902b39a947ddc480975717fddcd1..2c6c18cc51cd7daf36067031c163ae580fc4dcc3 100644 (file)
@@ -148,8 +148,8 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                     ],
                 },
                 explicit_self: borrowed_explicit_self(),
-                args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
-                           Borrowed(None, Mutability::Mutable))],
+                args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
+                           Borrowed(None, Mutability::Mutable)), "s")],
                 ret_ty: Literal(Path::new_(
                     pathvec_std!(cx, result::Result),
                     None,
index 1f80385cfbd24051b7acf05733918f02ba699a54..1ef0d2b0b4931be33057d9148e21a769696bb846 100644 (file)
@@ -252,7 +252,7 @@ pub struct MethodDef<'a> {
     pub explicit_self: Option<Option<PtrTy<'a>>>,
 
     /// Arguments other than the self argument
-    pub args: Vec<Ty<'a>>,
+    pub args: Vec<(Ty<'a>, &'a str)>,
 
     /// Return type
     pub ret_ty: Ty<'a>,
@@ -915,9 +915,9 @@ fn split_self_nonself_args
             explicit_self
         });
 
-        for (i, ty) in self.args.iter().enumerate() {
+        for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = cx.ident_of(&format!("__arg_{}", i));
+            let ident = cx.ident_of(name).gensym();
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -1004,10 +1004,10 @@ fn create_method(&self,
     ///
     /// // equivalent to:
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> bool {
+    ///     fn eq(&self, other: &A) -> bool {
     ///         match *self {
     ///             A {x: ref __self_0_0, y: ref __self_0_1} => {
-    ///                 match *__arg_1 {
+    ///                 match *other {
     ///                     A {x: ref __self_1_0, y: ref __self_1_1} => {
     ///                         __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
     ///                     }
@@ -1020,10 +1020,10 @@ fn create_method(&self,
     /// // or if A is repr(packed) - note fields are matched by-value
     /// // instead of by-reference.
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> bool {
+    ///     fn eq(&self, other: &A) -> bool {
     ///         match *self {
     ///             A {x: __self_0_0, y: __self_0_1} => {
-    ///                 match __arg_1 {
+    ///                 match other {
     ///                     A {x: __self_1_0, y: __self_1_1} => {
     ///                         __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1)
     ///                     }
@@ -1134,14 +1134,14 @@ fn expand_static_struct_method_body(&self,
     /// // is equivalent to
     ///
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> ::bool {
-    ///         match (&*self, &*__arg_1) {
+    ///     fn eq(&self, other: &A) -> ::bool {
+    ///         match (&*self, &*other) {
     ///             (&A1, &A1) => true,
     ///             (&A2(ref self_0),
     ///              &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)),
     ///             _ => {
     ///                 let __self_vi = match *self { A1(..) => 0, A2(..) => 1 };
-    ///                 let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 };
+    ///                 let __arg_1_vi = match *other { A1(..) => 0, A2(..) => 1 };
     ///                 false
     ///             }
     ///         }
@@ -1240,7 +1240,7 @@ fn build_enum_match_tuple<'b>(&self,
         let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                cx.ident_of(&vi_suffix[..])
+                cx.ident_of(&vi_suffix[..]).gensym()
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1616,7 +1616,7 @@ fn create_struct_pattern
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = cx.ident_of(&format!("{}_{}", prefix, i));
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym();
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
index b192ab2527e4b8f04319cfb6e006f3665bff8643..67096cdb49a3c5da2d589f47c4978b8a12a9cc3d 100644 (file)
@@ -44,8 +44,8 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                               bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])],
                           },
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![Ptr(Box::new(Literal(arg)),
-                                         Borrowed(None, Mutability::Mutable))],
+                          args: vec![(Ptr(Box::new(Literal(arg)),
+                                         Borrowed(None, Mutability::Mutable)), "state")],
                           ret_ty: nil_ty(),
                           attributes: vec![],
                           is_unsafe: false,
index c78decb1eb9d0bc2983a94c75974fe9c8e4a0a22..6b155b6596d08c80cd50d1e09564ceba91ac2aa1 100644 (file)
@@ -543,6 +543,10 @@ fn into_expr(self) -> P<ast::Expr> {
         let mut pats = Vec::new();
         let mut heads = Vec::new();
 
+        let names_pos: Vec<_> = (0..self.args.len()).map(|i| {
+            self.ecx.ident_of(&format!("arg{}", i)).gensym()
+        }).collect();
+
         // First, build up the static array which will become our precompiled
         // format "string"
         let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
@@ -560,7 +564,7 @@ fn into_expr(self) -> P<ast::Expr> {
         // of each variable because we don't want to move out of the arguments
         // passed to this function.
         for (i, e) in self.args.into_iter().enumerate() {
-            let name = self.ecx.ident_of(&format!("__arg{}", i));
+            let name = names_pos[i];
             let span =
                 DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark));
             pats.push(self.ecx.pat_ident(span, name));
@@ -570,14 +574,12 @@ fn into_expr(self) -> P<ast::Expr> {
             heads.push(self.ecx.expr_addr_of(e.span, e));
         }
         for pos in self.count_args {
-            let name = self.ecx.ident_of(&match pos {
-                Exact(i) => format!("__arg{}", i),
-                _ => panic!("should never happen"),
-            });
-            let span = match pos {
-                Exact(i) => spans_pos[i],
+            let index = match pos {
+                Exact(i) => i,
                 _ => panic!("should never happen"),
             };
+            let name = names_pos[index];
+            let span = spans_pos[index];
             counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
         }
 
index b449c5eea6658e7cdda063f0dac41b2c467bf008..556ee162c6ef2974dfc51fe5ef1caf2e98059088 100644 (file)
@@ -53,6 +53,10 @@ pub fn without_first_quote(self) -> Ident {
     pub fn modern(self) -> Ident {
         Ident::new(self.name, self.span.modern())
     }
+
+    pub fn gensym(self) -> Ident {
+        Ident::new(self.name.gensymed(), self.span)
+    }
 }
 
 impl PartialEq for Ident {
index 501c66e75cded115892fddfe02c0be9588b0c9c0..9b9deb4ca8d9d9cbef5304fd34a13d4447a388f0 100644 (file)
@@ -12,6 +12,7 @@
 const B: i32 = (&A)[1];
 //~^ ERROR constant evaluation error
 //~| index out of bounds: the len is 0 but the index is 1
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = B;
index d3b43e83bfe5218ac914584e6424f6fd4ee4a9d4..46feb20cf11ddbda624db1055b74db74476b9965 100644 (file)
@@ -12,6 +12,7 @@
 const B: i32 = A[1];
 //~^ ERROR constant evaluation error
 //~| index out of bounds: the len is 0 but the index is 1
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = B;
index 3de0f1ff61e1cb4c148ba5ec1a3a7ba99bb7df7d..6caec159d019ce39ce7f9bd1d65f64a561aa9b53 100644 (file)
 
 #![deny(const_err)]
 
-pub const A: i8 = -std::i8::MIN; //~ ERROR E0080
-//~^ ERROR attempt to negate with overflow
+pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
 //~| ERROR constant evaluation error
-pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080
-//~^ ERROR attempt to add with overflow
-pub const C: u8 = 200u8 * 4; //~ ERROR E0080
-//~^ ERROR attempt to multiply with overflow
-pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080
-//~^ ERROR attempt to subtract with overflow
+pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
+pub const C: u8 = 200u8 * 4; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
+pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
+//~^ ERROR this constant cannot be used
 pub const E: u8 = [5u8][1];
-//~^ ERROR E0080
+//~^ ERROR const_err
 
 fn main() {
     let _a = A;
index d2355f57f17294c5ed97c40a951d97b4de2764d9..6f0281b8bd0ca7382bf595d54137dae3a5b852a7 100644 (file)
 //~^ ERROR E0080
 //~| ERROR attempt to negate with overflow
 //~| ERROR constant evaluation error
+//~| ERROR this constant cannot be used
 pub const B: i8 = A;
-//~^ ERROR E0080
+//~^ ERROR const_err
 pub const C: u8 = A as u8;
-//~^ ERROR E0080
+//~^ ERROR const_err
 pub const D: i8 = 50 - A;
-//~^ ERROR E0080
+//~^ ERROR const_err
 
 fn main() {
     let _ = (A, B, C, D);
index a0d8f9672c05e1519ffb37e72705dae40315ca4e..faa8c3039b78cdfe0aae394a6428ea16b9adc8bd 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 fn main() {
index 08128f90e532f368a16185a155bcbe0b5ac13104..d827e680c5bbbec49cad32f782b1b96cda6764d8 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 fn main() {
index 31a1638cade170e7fecbf058fd4266937d22093c..2fd46b038ef28d7e62b9f98fcec95e360ba5c119 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 fn main() {
index 179ea9e853f3ad6bd4a4abc7973ee4fb40e7203d..7da5a2f17eaf90960d6339474ec99ddd2a509b47 100644 (file)
@@ -14,6 +14,7 @@
 const BAR: u32 = FOO[5];
 //~^ ERROR constant evaluation error [E0080]
 //~| index out of bounds: the len is 3 but the index is 5
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = BAR;
index f485982e2d3bc2c1b6eed767e972661e33c88ba6..6d5e82c68cc8ed883c27e7d8bc504e2c681344d8 100644 (file)
@@ -58,7 +58,7 @@ fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
         name: "eq",
         generics: LifetimeBounds::empty(),
         explicit_self: borrowed_explicit_self(),
-        args: vec![borrowed_self()],
+        args: vec![(borrowed_self(), "other")],
         ret_ty: Literal(deriving::generic::ty::Path::new_local("bool")),
         attributes: attrs,
         is_unsafe: false,
diff --git a/src/test/run-pass-fulldeps/deriving-hygiene.rs b/src/test/run-pass-fulldeps/deriving-hygiene.rs
new file mode 100644 (file)
index 0000000..532f245
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 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.
+
+#![feature(rustc_private)]
+extern crate serialize;
+
+pub const other: u8 = 1;
+pub const f: u8 = 1;
+pub const d: u8 = 1;
+pub const s: u8 = 1;
+pub const state: u8 = 1;
+pub const cmp: u8 = 1;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,Decodable,Encodable,Hash)]
+struct Foo {}
+
+fn main() {
+}
diff --git a/src/test/run-pass/compiletest-skip-trans.rs b/src/test/run-pass/compiletest-skip-trans.rs
new file mode 100644 (file)
index 0000000..d24a650
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 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.
+
+// Test that with the `skip-trans` option the test isn't executed.
+
+// skip-trans
+
+fn main() {
+    unreachable!();
+}
diff --git a/src/test/run-pass/format-hygiene.rs b/src/test/run-pass/format-hygiene.rs
new file mode 100644 (file)
index 0000000..6971f77
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 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 const arg0: u8 = 1;
+
+pub fn main() {
+    format!("{}", 1);
+}
index e059c354d65a73151a3d06d8d9b57077cc1e59dd..dbddee862e022a87d3521e58ffec761291acf78b 100644 (file)
@@ -14,6 +14,7 @@
 const Y: u32 = 6;
 const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
 //~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
 
 fn main() {
     println!("{}", FOO);
index fd29990fec295abd5c0d807b663020bec0c72a26..713b1b36c08b1b0c55f807d0eee174608f2e45a4 100644 (file)
@@ -6,8 +6,14 @@ LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |
    = note: #[warn(const_err)] on by default
 
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
 warning: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:19:20
+  --> $DIR/conditional_array_execution.rs:20:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
index b27791ef5337b7c7039d1005e2464e5b452521d5..097fba4d3c45094b98152e68372b8878b789539e 100644 (file)
@@ -19,8 +19,10 @@ const fn foo(x: u32) -> u32 {
 fn main() {
     const X: u32 = 0-1;
     //~^ WARN attempt to subtract with overflow
+    //~| WARN this constant cannot be used
     const Y: u32 = foo(0-1);
     //~^ WARN attempt to subtract with overflow
+    //~| WARN this constant cannot be used
     println!("{} {}", X, Y);
     //~^ WARN constant evaluation error
     //~| WARN constant evaluation error
index 5da47a85eb803f3b1b79e8179d72b93856dfa020..a22e8016296c4f95a3b2fe53907d52bd39a71db4 100644 (file)
@@ -6,20 +6,32 @@ LL |     const X: u32 = 0-1;
    |
    = note: #[warn(const_err)] on by default
 
-warning: constant evaluation error
-  --> $DIR/issue-43197.rs:24:23
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:20:5
    |
-LL |     println!("{} {}", X, Y);
-   |                       ^ referenced constant has errors
+LL |     const X: u32 = 0-1;
+   |     ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:22:24
+  --> $DIR/issue-43197.rs:23:24
    |
 LL |     const Y: u32 = foo(0-1);
    |                        ^^^
 
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:23:5
+   |
+LL |     const Y: u32 = foo(0-1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+warning: constant evaluation error
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
 warning: constant evaluation error
-  --> $DIR/issue-43197.rs:24:26
+  --> $DIR/issue-43197.rs:26:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
index bdb9f5b19a88541088a6cbcce2be7827e721fc24..c6bf07649af38a17dd33964436037a59b06d0493 100644 (file)
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(const_err)]
+// compile-pass
 
 #![crate_type = "lib"]
 
 pub const Z: u32 = 0 - 1;
-//~^ ERROR attempt to subtract with overflow
+//~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
+
+pub type Foo = [i32; 0 - 1];
+//~^ WARN attempt to subtract with overflow
+//~| WARN this array length cannot be used
index b77ec38ca1679869a692892c8d8ed94bf3d795f9..2981ac20cd981d639a426fd082a0486e2e4ff147 100644 (file)
@@ -1,14 +1,26 @@
-error: attempt to subtract with overflow
+warning: attempt to subtract with overflow
   --> $DIR/pub_const_err.rs:15:20
    |
 LL | pub const Z: u32 = 0 - 1;
    |                    ^^^^^
    |
-note: lint level defined here
-  --> $DIR/pub_const_err.rs:11:9
+   = note: #[warn(const_err)] on by default
+
+warning: this constant cannot be used
+  --> $DIR/pub_const_err.rs:15:1
    |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
+LL | pub const Z: u32 = 0 - 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
-error: aborting due to previous error
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err.rs:19:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^
+
+warning: this array length cannot be used
+  --> $DIR/pub_const_err.rs:19:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^ attempt to subtract with overflow
 
diff --git a/src/test/ui/const-eval/pub_const_err_bin.rs b/src/test/ui/const-eval/pub_const_err_bin.rs
new file mode 100644 (file)
index 0000000..d87cb7e
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+// compile-pass
+
+pub const Z: u32 = 0 - 1;
+//~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
+
+pub type Foo = [i32; 0 - 1];
+//~^ WARN attempt to subtract with overflow
+//~| WARN this array length cannot be used
+
+fn main() {}
diff --git a/src/test/ui/const-eval/pub_const_err_bin.stderr b/src/test/ui/const-eval/pub_const_err_bin.stderr
new file mode 100644 (file)
index 0000000..3e8966d
--- /dev/null
@@ -0,0 +1,26 @@
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err_bin.rs:13:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   |                    ^^^^^
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: this constant cannot be used
+  --> $DIR/pub_const_err_bin.rs:13:1
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err_bin.rs:17:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^
+
+warning: this array length cannot be used
+  --> $DIR/pub_const_err_bin.rs:17:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^ attempt to subtract with overflow
+
diff --git a/src/test/ui/edition-lint-paths.rs b/src/test/ui/edition-lint-paths.rs
new file mode 100644 (file)
index 0000000..0b49e72
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2018 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.
+
+#![feature(crate_in_paths)]
+#![deny(absolute_path_starting_with_module)]
+#![allow(unused)]
+
+pub mod foo {
+    use ::bar::Bar;
+    //~^ ERROR Absolute
+    //~| WARN this was previously accepted
+    use super::bar::Bar2;
+    use crate::bar::Bar3;
+}
+
+
+use bar::Bar;
+//~^ ERROR Absolute
+//~| WARN this was previously accepted
+
+pub mod bar {
+    pub struct Bar;
+    pub type Bar2 = Bar;
+    pub type Bar3 = Bar;
+}
+
+fn main() {
+    let x = ::bar::Bar;
+    //~^ ERROR Absolute
+    //~| WARN this was previously accepted
+    let x = bar::Bar;
+    let x = ::crate::bar::Bar;
+    let x = self::bar::Bar;
+}
diff --git a/src/test/ui/edition-lint-paths.stderr b/src/test/ui/edition-lint-paths.stderr
new file mode 100644 (file)
index 0000000..509527e
--- /dev/null
@@ -0,0 +1,34 @@
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:16:9
+   |
+LL |     use ::bar::Bar;
+   |         ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-paths.rs:12:9
+   |
+LL | #![deny(absolute_path_starting_with_module)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:24:5
+   |
+LL | use bar::Bar;
+   |     ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:35:13
+   |
+LL |     let x = ::bar::Bar;
+   |             ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: aborting due to 3 previous errors
+
index 3795704466a2372f5bea14de53b767c50386be6d..73dd079cf0ccb8f40e1cc4a494519cb9dfaaab37 100644 (file)
@@ -228,6 +228,8 @@ pub struct TestProps {
     pub check_test_line_numbers_match: bool,
     // The test must be compiled and run successfully. Only used in UI tests for now.
     pub run_pass: bool,
+    // Skip any codegen step and running the executable. Only for run-pass.
+    pub skip_trans: bool,
     // Do not pass `-Z ui-testing` to UI tests
     pub disable_ui_testing_normalization: bool,
     // customized normalization rules
@@ -260,6 +262,7 @@ pub fn new() -> Self {
             compile_pass: false,
             check_test_line_numbers_match: false,
             run_pass: false,
+            skip_trans: false,
             disable_ui_testing_normalization: false,
             normalize_stdout: vec![],
             normalize_stderr: vec![],
@@ -381,6 +384,10 @@ fn load_from(&mut self,
                     config.parse_compile_pass(ln) || self.run_pass;
             }
 
+                        if !self.skip_trans {
+                            self.skip_trans = config.parse_skip_trans(ln);
+                        }
+
             if !self.disable_ui_testing_normalization {
                 self.disable_ui_testing_normalization =
                     config.parse_disable_ui_testing_normalization(ln);
@@ -524,6 +531,10 @@ fn parse_run_pass(&self, line: &str) -> bool {
         self.parse_name_directive(line, "run-pass")
     }
 
+    fn parse_skip_trans(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "skip-trans")
+    }
+
     fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> {
         self.parse_name_value_directive(line, name).map(|nv| {
             // nv is either FOO or FOO=BAR
index aabf2e6f8f0e675c2e918e7491c1cd59546c75d0..85434bb8a69b8a70290c8eca9caf17601282b22b 100644 (file)
@@ -343,9 +343,11 @@ fn run_rpass_test(&self) {
             "run-pass tests with expected warnings should be moved to ui/"
         );
 
-        let proc_res = self.exec_compiled_test();
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("test run failed!", &proc_res);
+        if !self.props.skip_trans {
+            let proc_res = self.exec_compiled_test();
+            if !proc_res.status.success() {
+                self.fatal_proc_rec("test run failed!", &proc_res);
+            }
         }
     }
 
@@ -1697,6 +1699,11 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
             }
         }
 
+        if self.props.skip_trans {
+            assert!(!self.props.compile_flags.iter().any(|s| s.starts_with("--emit")));
+            rustc.args(&["--emit", "metadata"]);
+        }
+
         if !is_rustdoc {
             if self.config.target == "wasm32-unknown-unknown" {
                 // rustc.arg("-g"); // get any backtrace at all on errors