"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,
TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIME_IN_PATH,
BARE_TRAIT_OBJECT,
+ ABSOLUTE_PATH_STARTING_WITH_MODULE,
UNSTABLE_NAME_COLLISION,
)
}
#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
pub enum BuiltinLintDiagnostics {
Normal,
- BareTraitObject(Span, /* is_global */ bool)
+ BareTraitObject(Span, /* is_global */ bool),
+ AbsPathWithModule(Span),
}
impl BuiltinLintDiagnostics {
};
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);
+ }
}
}
}
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); }
// 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);
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;
-> 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!()
+ }
}
}
/// 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>,
// 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()
},
}
}
}
+
+/// 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
+ ),
+ _ => {},
+ }
+ }
+}
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;
UnionsWithDropFields,
UnreachablePub,
TypeAliasBounds,
+ UnusedBrokenConst,
);
add_builtin_with_new!(sess,
// 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
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));
}
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()));
}
}
(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()));
));
}
- 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())
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),
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;
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);
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) => {
// 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);
}
}
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 @ _ => {
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));
// 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 {
}
}
- 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) => {
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[..]))))
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();
trans_worker_send,
coordinator_receive,
total_cgus,
- client,
+ sess.jobserver.clone(),
time_graph.clone(),
Arc::new(modules_config),
Arc::new(metadata_config),
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,
}
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"]);
// ::std::cmp::Ordering::Equal => {
// ...
// }
- // __cmp => __cmp
+ // cmp => cmp
// },
- // __cmp => __cmp
+ // cmp => cmp
// }
//
cs_fold(// foldr nests the if-elses correctly, leaving the first field
|cx, span, old, self_f, other_fs| {
// match new {
// ::std::cmp::Ordering::Equal => old,
- // __cmp => __cmp
+ // cmp => cmp
// }
let new = {
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,
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,
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,
}
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);
// ::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
|cx, span, old, self_f, other_fs| {
// match new {
// Some(::std::cmp::Ordering::Equal) => old,
- // __cmp => __cmp
+ // cmp => cmp
// }
let new = {
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,
// 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();
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,
],
},
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,
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>,
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);
///
/// // 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)
/// }
/// // 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)
/// }
/// // 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
/// }
/// }
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>>();
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 {
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,
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);
// 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));
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));
}
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 {
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;
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;
#![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;
//~^ 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);
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() {
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() {
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() {
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;
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,
--- /dev/null
+// 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() {
+}
--- /dev/null
+// 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!();
+}
--- /dev/null
+// 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);
+}
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);
|
= 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
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
|
= 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
// 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
-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
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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;
+}
--- /dev/null
+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
+
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
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![],
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);
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
"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);
+ }
}
}
}
}
+ 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