diff options
Diffstat (limited to 'src')
463 files changed, 10735 insertions, 2877 deletions
diff --git a/src/doc/not_found.md b/src/doc/not_found.md index ebe7c59313f..f404aa046c1 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -13,20 +13,20 @@ Some things that might be helpful to you though: # Search -* <form action="https://duckduckgo.com/"> +<form action="https://duckduckgo.com/"> <input type="text" id="site-search" name="q" size="80"></input> - <input type="submit" value="Search DuckDuckGo"> -</form> -* Rust doc search: <span id="core-search"></span> + <input type="submit" value="Search DuckDuckGo"></form> + +Rust doc search: <span id="core-search"></span> # Reference -* [The Rust official site](https://www.rust-lang.org) -* [The Rust reference](https://doc.rust-lang.org/reference/index.html) + * [The Rust official site](https://www.rust-lang.org) + * [The Rust reference](https://doc.rust-lang.org/reference/index.html) # Docs -* [The standard library](https://doc.rust-lang.org/std/) +[The standard library](https://doc.rust-lang.org/std/) <script> function get_url_fragments() { diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index d4cd3f6264e..93cfc845b1f 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1084,9 +1084,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> { pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U> where F: FnOnce(&mut T) -> &mut U { + // FIXME(nll-rfc#40): fix borrow-check + let RefMut { value, borrow } = orig; RefMut { - value: f(orig.value), - borrow: orig.borrow, + value: f(value), + borrow: borrow, } } } diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index e173f43b5e6..06c29b47bf9 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1776,12 +1776,18 @@ impl<I: Iterator> Iterator for Peekable<I> { #[inline] fn nth(&mut self, n: usize) -> Option<I::Item> { - match self.peeked.take() { - // the .take() below is just to avoid "move into pattern guard" - Some(ref mut v) if n == 0 => v.take(), - Some(None) => None, - Some(Some(_)) => self.iter.nth(n - 1), - None => self.iter.nth(n), + // FIXME(#6393): merge these when borrow-checking gets better. + if n == 0 { + match self.peeked.take() { + Some(v) => v, + None => self.iter.nth(n), + } + } else { + match self.peeked.take() { + Some(None) => None, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), + } } } diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index fe2df226115..948ad104cdf 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -736,7 +736,7 @@ mod builtin { #[cfg(dox)] macro_rules! module_path { () => ({ /* compiler built-in */ }) } - /// Boolean evaluation of configuration flags. + /// Boolean evaluation of configuration flags, at compile-time. /// /// For more information, see the documentation for [`std::cfg!`]. /// diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 12e6e843056..d8f3ec38cf3 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -338,6 +338,12 @@ impl<T> Option<T> { /// Returns the contained value or a default. /// + /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`unwrap_or_else`], + /// which is lazily evaluated. + /// + /// [`unwrap_or_else`]: #method.unwrap_or_else + /// /// # Examples /// /// ``` @@ -451,11 +457,16 @@ impl<T> Option<T> { /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to /// [`Ok(v)`] and [`None`] to [`Err(err)`]. /// + /// Arguments passed to `ok_or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`ok_or_else`], which is + /// lazily evaluated. + /// /// [`Result<T, E>`]: ../../std/result/enum.Result.html /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err /// [`None`]: #variant.None /// [`Some(v)`]: #variant.Some + /// [`ok_or_else`]: #method.ok_or_else /// /// # Examples /// @@ -644,6 +655,12 @@ impl<T> Option<T> { /// Returns the option if it contains a value, otherwise returns `optb`. /// + /// Arguments passed to `or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`or_else`], which is + /// lazily evaluated. + /// + /// [`or_else`]: #method.or_else + /// /// # Examples /// /// ``` diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 959935242dc..2ace3d2aee8 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -625,8 +625,13 @@ impl<T, E> Result<T, E> { /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. /// + /// Arguments passed to `or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`or_else`], which is + /// lazily evaluated. + /// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Err`]: enum.Result.html#variant.Err + /// [`or_else`]: #method.or_else /// /// # Examples /// @@ -690,8 +695,13 @@ impl<T, E> Result<T, E> { /// Unwraps a result, yielding the content of an [`Ok`]. /// Else, it returns `optb`. /// + /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`unwrap_or_else`], + /// which is lazily evaluated. + /// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Err`]: enum.Result.html#variant.Err + /// [`unwrap_or_else`]: #method.unwrap_or_else /// /// # Examples /// diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 8089a88a9e8..85ae529ae32 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1641,14 +1641,14 @@ impl Foo { These attributes do not work on typedefs, since typedefs are just aliases. Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the -discriminant size for C-like enums (when there is no associated data, e.g. -`enum Color {Red, Blue, Green}`), effectively setting the size of the enum to +discriminant size for enums with no data fields on any of the variants, e.g. +`enum Color {Red, Blue, Green}`, effectively setting the size of the enum to the size of the provided type. Such an enum can be cast to a value of the same type as well. In short, `#[repr(u8)]` makes the enum behave like an integer with a constrained set of allowed values. -Only C-like enums can be cast to numerical primitives, so this attribute will -not apply to structs. +Only field-less enums can be cast to numerical primitives, so this attribute +will not apply to structs. `#[repr(packed)]` reduces padding to make the struct size smaller. The representation of enums isn't strictly defined in Rust, and this attribute diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index d95b825b9e5..0ef42177c14 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -14,7 +14,6 @@ use hir::map::DefPathHash; use hir::map::definitions::Definitions; use ich::{self, CachingCodemapView}; use middle::cstore::CrateStore; -use session::config::DebugInfoLevel::NoDebugInfo; use ty::{TyCtxt, fast_reject}; use session::Session; @@ -24,7 +23,7 @@ use std::cell::RefCell; use std::collections::HashMap; use syntax::ast; -use syntax::attr; + use syntax::codemap::CodeMap; use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::Symbol; @@ -51,7 +50,6 @@ pub struct StableHashingContext<'gcx> { body_resolver: BodyResolver<'gcx>, hash_spans: bool, hash_bodies: bool, - overflow_checks_enabled: bool, node_id_hashing_mode: NodeIdHashingMode, // Very often, we are hashing something that does not need the @@ -89,8 +87,7 @@ impl<'gcx> StableHashingContext<'gcx> { definitions: &'gcx Definitions, cstore: &'gcx CrateStore) -> Self { - let hash_spans_initial = sess.opts.debuginfo != NoDebugInfo; - let check_overflow_initial = sess.overflow_checks(); + let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans; debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0); IGNORED_ATTR_NAMES.with(|names| { @@ -110,7 +107,6 @@ impl<'gcx> StableHashingContext<'gcx> { raw_codemap: sess.codemap(), hash_spans: hash_spans_initial, hash_bodies: true, - overflow_checks_enabled: check_overflow_initial, node_id_hashing_mode: NodeIdHashingMode::HashDefPath, } } @@ -120,11 +116,6 @@ impl<'gcx> StableHashingContext<'gcx> { self.sess } - pub fn force_span_hashing(mut self) -> Self { - self.hash_spans = true; - self - } - #[inline] pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, @@ -175,11 +166,6 @@ impl<'gcx> StableHashingContext<'gcx> { } #[inline] - pub fn hash_spans(&self) -> bool { - self.hash_spans - } - - #[inline] pub fn hash_bodies(&self) -> bool { self.hash_bodies } @@ -204,58 +190,13 @@ impl<'gcx> StableHashingContext<'gcx> { }) } - pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, - item_attrs: &[ast::Attribute], - is_const: bool, - f: F) { - let prev_overflow_checks = self.overflow_checks_enabled; - if is_const || attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") { - self.overflow_checks_enabled = true; - } + pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) { let prev_hash_node_ids = self.node_id_hashing_mode; self.node_id_hashing_mode = NodeIdHashingMode::Ignore; f(self); self.node_id_hashing_mode = prev_hash_node_ids; - self.overflow_checks_enabled = prev_overflow_checks; - } - - #[inline] - pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool - { - match binop { - hir::BiAdd | - hir::BiSub | - hir::BiShl | - hir::BiShr | - hir::BiMul => self.overflow_checks_enabled, - - hir::BiDiv | - hir::BiRem => true, - - hir::BiAnd | - hir::BiOr | - hir::BiBitXor | - hir::BiBitAnd | - hir::BiBitOr | - hir::BiEq | - hir::BiLt | - hir::BiLe | - hir::BiNe | - hir::BiGe | - hir::BiGt => false - } - } - - #[inline] - pub fn unop_can_panic_at_runtime(&self, unop: hir::UnOp) -> bool - { - match unop { - hir::UnDeref | - hir::UnNot => false, - hir::UnNeg => self.overflow_checks_enabled, - } } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 77bf3da679d..1533e37d7f7 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -529,63 +529,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Expr { ref attrs } = *self; - let spans_always_on = match *node { - hir::ExprBox(..) | - hir::ExprArray(..) | - hir::ExprCall(..) | - hir::ExprLit(..) | - hir::ExprCast(..) | - hir::ExprType(..) | - hir::ExprIf(..) | - hir::ExprWhile(..) | - hir::ExprLoop(..) | - hir::ExprMatch(..) | - hir::ExprClosure(..) | - hir::ExprBlock(..) | - hir::ExprAssign(..) | - hir::ExprTupField(..) | - hir::ExprAddrOf(..) | - hir::ExprBreak(..) | - hir::ExprAgain(..) | - hir::ExprRet(..) | - hir::ExprYield(..) | - hir::ExprInlineAsm(..) | - hir::ExprRepeat(..) | - hir::ExprTup(..) | - hir::ExprMethodCall(..) | - hir::ExprPath(..) | - hir::ExprStruct(..) | - hir::ExprField(..) => { - // For these we only hash the span when debuginfo is on. - false - } - // For the following, spans might be significant because of - // panic messages indicating the source location. - hir::ExprBinary(op, ..) => { - hcx.binop_can_panic_at_runtime(op.node) - } - hir::ExprUnary(op, _) => { - hcx.unop_can_panic_at_runtime(op) - } - hir::ExprAssignOp(op, ..) => { - hcx.binop_can_panic_at_runtime(op.node) - } - hir::ExprIndex(..) => { - true - } - }; - - if spans_always_on { - hcx.while_hashing_spans(true, |hcx| { - span.hash_stable(hcx, hasher); - node.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - }); - } else { - span.hash_stable(hcx, hasher); - node.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - } + span.hash_stable(hcx, hasher); + node.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); }) } } @@ -712,15 +658,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem { span } = *self; - let is_const = match *node { - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(..) => true, - hir::TraitItemKind::Method(hir::MethodSig { constness, .. }, _) => { - constness == hir::Constness::Const - } - }; - - hcx.hash_hir_item_like(attrs, is_const, |hcx| { + hcx.hash_hir_item_like(|hcx| { name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); generics.hash_stable(hcx, hasher); @@ -757,15 +695,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem { span } = *self; - let is_const = match *node { - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(..) => true, - hir::ImplItemKind::Method(hir::MethodSig { constness, .. }, _) => { - constness == hir::Constness::Const - } - }; - - hcx.hash_hir_item_like(attrs, is_const, |hcx| { + hcx.hash_hir_item_like(|hcx| { name.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher); defaultness.hash_stable(hcx, hasher); @@ -884,30 +814,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item { fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher<W>) { - let is_const = match self.node { - hir::ItemStatic(..) | - hir::ItemConst(..) => { - true - } - hir::ItemFn(_, _, constness, ..) => { - constness == hir::Constness::Const - } - hir::ItemUse(..) | - hir::ItemExternCrate(..) | - hir::ItemForeignMod(..) | - hir::ItemGlobalAsm(..) | - hir::ItemMod(..) | - hir::ItemAutoImpl(..) | - hir::ItemTrait(..) | - hir::ItemImpl(..) | - hir::ItemTy(..) | - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemUnion(..) => { - false - } - }; - let hir::Item { name, ref attrs, @@ -918,7 +824,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item { span } = *self; - hcx.hash_hir_item_like(attrs, is_const, |hcx| { + hcx.hash_hir_item_like(|hcx| { name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 331b44ac119..32577ac46f3 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -55,48 +55,11 @@ for mir::UnsafetyViolationKind { } } } -impl<'gcx> HashStable<StableHashingContext<'gcx>> -for mir::Terminator<'gcx> { - #[inline] - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut StableHashingContext<'gcx>, - hasher: &mut StableHasher<W>) { - let mir::Terminator { - ref kind, - ref source_info, - } = *self; - - let hash_spans_unconditionally = match *kind { - mir::TerminatorKind::Assert { .. } => { - // Assert terminators generate a panic message that contains the - // source location, so we always have to feed its span into the - // ICH. - true - } - mir::TerminatorKind::Goto { .. } | - mir::TerminatorKind::SwitchInt { .. } | - mir::TerminatorKind::Resume | - mir::TerminatorKind::Return | - mir::TerminatorKind::GeneratorDrop | - mir::TerminatorKind::Unreachable | - mir::TerminatorKind::Drop { .. } | - mir::TerminatorKind::DropAndReplace { .. } | - mir::TerminatorKind::Yield { .. } | - mir::TerminatorKind::Call { .. } | - mir::TerminatorKind::FalseEdges { .. } => false, - }; - - if hash_spans_unconditionally { - hcx.while_hashing_spans(true, |hcx| { - source_info.hash_stable(hcx, hasher); - }) - } else { - source_info.hash_stable(hcx, hasher); - } - kind.hash_stable(hcx, hasher); - } -} +impl_stable_hash_for!(struct mir::Terminator<'tcx> { + kind, + source_info +}); impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearCrossCrate<T> where T: HashStable<StableHashingContext<'gcx>> @@ -572,3 +535,15 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> { } impl_stable_hash_for!(struct mir::Location { block, statement_index }); + +impl_stable_hash_for!(struct mir::ClosureRegionRequirements { + num_external_vids, + outlives_requirements +}); + +impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement { + free_region, + outlived_free_region, + blame_span +}); + diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9609ae5a0be..2655e2acbbd 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -84,6 +84,16 @@ for ty::RegionKind { } } +impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::RegionVid { + #[inline] + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher<W>) { + use rustc_data_structures::indexed_vec::Idx; + self.index().hash_stable(hcx, hasher); + } +} + impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::adjustment::AutoBorrow<'gcx> { fn hash_stable<W: StableHasherResult>(&self, diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 96a980a1545..f5595d07340 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1062,6 +1062,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin))) } + /// Number of region variables created so far. + pub fn num_region_vars(&self) -> usize { + self.borrow_region_constraints().var_origins().len() + } + /// Just a convenient wrapper of `next_region_var` for using during NLL. pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin) -> ty::Region<'tcx> { @@ -1475,38 +1480,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { closure_kind_ty.to_opt_closure_kind() } - /// Obtain the signature of a function or closure. - /// For closures, unlike `tcx.fn_sig(def_id)`, this method will - /// work during the type-checking of the enclosing function and - /// return the closure signature in its partially inferred state. - pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - // Do we have an in-progress set of tables we are inferring? - if let Some(tables) = self.in_progress_tables { - // Is this a local item? - if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - // Is it a local *closure*? - if self.tcx.is_closure(def_id) { - let hir_id = self.tcx.hir.node_to_hir_id(id); - // Is this local closure contained within the tables we are inferring? - if tables.borrow().local_id_root == Some(DefId::local(hir_id.owner)) { - // if so, extract signature from there. - let closure_ty = tables.borrow().node_id_to_type(hir_id); - let (closure_def_id, closure_substs) = match closure_ty.sty { - ty::TyClosure(closure_def_id, closure_substs) => - (closure_def_id, closure_substs), - _ => - bug!("closure with non-closure type: {:?}", closure_ty), - }; - assert_eq!(def_id, closure_def_id); - let closure_sig_ty = closure_substs.closure_sig_ty(def_id, self.tcx); - let closure_sig_ty = self.shallow_resolve(&closure_sig_ty); - return closure_sig_ty.fn_sig(self.tcx); - } - } - } - } - - self.tcx.fn_sig(def_id) + /// Obtain the signature of a closure. For closures, unlike + /// `tcx.fn_sig(def_id)`, this method will work during the + /// type-checking of the enclosing function and return the closure + /// signature in its partially inferred state. + pub fn closure_sig( + &self, + def_id: DefId, + substs: ty::ClosureSubsts<'tcx> + ) -> ty::PolyFnSig<'tcx> { + let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); + let closure_sig_ty = self.shallow_resolve(&closure_sig_ty); + closure_sig_ty.fn_sig(self.tcx) } /// Normalizes associated types in `value`, potentially returning diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c803e76aebe..64e601ab1e7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1789,6 +1789,75 @@ pub struct GeneratorLayout<'tcx> { pub fields: Vec<LocalDecl<'tcx>>, } +/// After we borrow check a closure, we are left with various +/// requirements that we have inferred between the free regions that +/// appear in the closure's signature or on its field types. These +/// requirements are then verified and proved by the closure's +/// creating function. This struct encodes those requirements. +/// +/// The requirements are listed as being between various +/// `RegionVid`. The 0th region refers to `'static`; subsequent region +/// vids refer to the free regions that appear in the closure (or +/// generator's) type, in order of appearance. (This numbering is +/// actually defined by the `UniversalRegions` struct in the NLL +/// region checker. See for example +/// `UniversalRegions::closure_mapping`.) Note that we treat the free +/// regions in the closure's type "as if" they were erased, so their +/// precise identity is not important, only their position. +/// +/// Example: If type check produces a closure with the closure substs: +/// +/// ``` +/// ClosureSubsts = [ +/// i8, // the "closure kind" +/// for<'x> fn(&'a &'x u32) -> &'x u32, // the "closure signature" +/// &'a String, // some upvar +/// ] +/// ``` +/// +/// here, there is one unique free region (`'a`) but it appears +/// twice. We would "renumber" each occurence to a unique vid, as follows: +/// +/// ``` +/// ClosureSubsts = [ +/// i8, // the "closure kind" +/// for<'x> fn(&'1 &'x u32) -> &'x u32, // the "closure signature" +/// &'2 String, // some upvar +/// ] +/// ``` +/// +/// Now the code might impose a requirement like `'1: '2`. When an +/// instance of the closure is created, the corresponding free regions +/// can be extracted from its type and constrained to have the given +/// outlives relationship. +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub struct ClosureRegionRequirements { + /// The number of external regions defined on the closure. In our + /// example above, it would be 3 -- one for `'static`, then `'1` + /// and `'2`. This is just used for a sanity check later on, to + /// make sure that the number of regions we see at the callsite + /// matches. + pub num_external_vids: usize, + + /// Requirements between the various free regions defined in + /// indices. + pub outlives_requirements: Vec<ClosureOutlivesRequirement>, +} + +/// Indicates an outlives constraint between two free-regions declared +/// on the closure. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +pub struct ClosureOutlivesRequirement { + // This region ... + pub free_region: ty::RegionVid, + + // .. must outlive this one. + pub outlived_free_region: ty::RegionVid, + + // If not, report an error here. + pub blame_span: Span, +} + /* * TypeFoldable implementations for MIR types */ diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 81e18fe536d..0dcd3e80810 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1084,6 +1084,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump hash information in textual format to stdout"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], "verify incr. comp. hashes of green query instances"), + incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], + "ignore spans during ICH computation -- used for testing"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 429771cca98..3342d13dd6e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1339,26 +1339,27 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>) -> Progress<'tcx> { - let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.fn_sig(vtable.closure_def_id) - .subst(selcx.tcx(), vtable.substs.substs); + let tcx = selcx.tcx(); + let infcx = selcx.infcx(); + let closure_sig_ty = vtable.substs.closure_sig_ty(vtable.closure_def_id, tcx); + let closure_sig = infcx.shallow_resolve(&closure_sig_ty).fn_sig(tcx); let Normalized { - value: closure_type, + value: closure_sig, obligations } = normalize_with_depth(selcx, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth+1, - &closure_type); + &closure_sig); - debug!("confirm_closure_candidate: obligation={:?},closure_type={:?},obligations={:?}", + debug!("confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}", obligation, - closure_type, + closure_sig, obligations); confirm_callable_candidate(selcx, obligation, - closure_type, + closure_sig, util::TupleArgumentsFlag::No) .with_addl_obligations(vtable.nested) .with_addl_obligations(obligations) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 0c4071b8b5d..e70de0e566e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3183,8 +3183,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.infcx.fn_sig(closure_def_id) - .subst(self.tcx(), substs.substs); + let closure_type = self.infcx.closure_sig(closure_def_id, substs); let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), obligation.predicate.0.self_ty(), // (1) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 70636f8b6fe..177c25ac5db 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; -use ty::subst::{Kind, Subst}; +use ty::subst::Kind; use traits; use syntax::abi::Abi; use util::ppaux; @@ -311,7 +311,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( let self_ty = tcx.mk_closure_from_closure_substs( closure_did, substs); - let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs); + let sig = substs.closure_sig(closure_did, tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 496284ad9c9..2d0a3799178 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -27,6 +27,7 @@ pub trait QueryConfig { pub(super) trait QueryDescription<'tcx>: QueryConfig { fn describe(tcx: TyCtxt, key: Self::Key) -> String; + #[inline] fn cache_on_disk(_: Self::Key) -> bool { false } @@ -34,7 +35,7 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig { fn try_load_from_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> { - bug!("QueryDescription::load_from_disk() called for unsupport query.") + bug!("QueryDescription::load_from_disk() called for an unsupported query.") } } @@ -166,6 +167,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> { fn describe(_tcx: TyCtxt, instance: ty::Instance<'tcx>) -> String { format!("computing the symbol for `{}`", instance) } + + #[inline] + fn cache_on_disk(_: Self::Key) -> bool { + true + } + + #[inline] + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option<Self::Value> { + tcx.on_disk_query_result_cache.try_load_query_result(tcx, id) + } } impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> { @@ -234,6 +247,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_sta format!("const checking if rvalue is promotable to static `{}`", tcx.item_path_str(def_id)) } + + #[inline] + fn cache_on_disk(_: Self::Key) -> bool { + true + } + + #[inline] + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option<Self::Value> { + tcx.on_disk_query_result_cache.try_load_query_result(tcx, id) + } } impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> { @@ -254,6 +279,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::trans_fulfill_obligation<'tcx> { fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String { format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id())) } + + #[inline] + fn cache_on_disk(_: Self::Key) -> bool { + true + } + + #[inline] + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option<Self::Value> { + tcx.on_disk_query_result_cache.try_load_query_result(tcx, id) + } } impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> { @@ -567,3 +604,42 @@ impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> { + #[inline] + fn cache_on_disk(def_id: Self::Key) -> bool { + def_id.is_local() + } + + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option<Self::Value> { + let mir: Option<::mir::Mir<'tcx>> = tcx.on_disk_query_result_cache + .try_load_query_result(tcx, id); + mir.map(|x| tcx.alloc_mir(x)) + } +} + +macro_rules! impl_disk_cacheable_query( + ($query_name:ident, |$key:tt| $cond:expr) => { + impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> { + #[inline] + fn cache_on_disk($key: Self::Key) -> bool { + $cond + } + + #[inline] + fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: SerializedDepNodeIndex) + -> Option<Self::Value> { + tcx.on_disk_query_result_cache.try_load_query_result(tcx, id) + } + } + } +); + +impl_disk_cacheable_query!(unsafety_check_result, |def_id| def_id.is_local()); +impl_disk_cacheable_query!(borrowck, |def_id| def_id.is_local()); +impl_disk_cacheable_query!(mir_borrowck, |def_id| def_id.is_local()); +impl_disk_cacheable_query!(mir_const_qualif, |def_id| def_id.is_local()); +impl_disk_cacheable_query!(contains_extern_indicator, |_| true); +impl_disk_cacheable_query!(def_symbol_name, |_| true); diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index fb3600182d8..848d2a0a7de 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -190,8 +190,10 @@ define_maps! { <'tcx> [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), [] fn borrowck: BorrowCheck(DefId) -> Rc<BorrowCheckResult>, - // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead? - [] fn mir_borrowck: MirBorrowCheck(DefId) -> (), + + /// Borrow checks the function body. If this is a closure, returns + /// additional requirements that the closure's creator must verify. + [] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements>, /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 8dc9b0877a0..079b518efd8 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -207,6 +207,16 @@ impl<'sess> OnDiskCache<'sess> { // Encode TypeckTables encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?; + encode_query_results::<optimized_mir, _>(tcx, enc, qri)?; + encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?; + encode_query_results::<borrowck, _>(tcx, enc, qri)?; + encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?; + encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?; + encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?; + encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?; + encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?; + encode_query_results::<symbol_name, _>(tcx, enc, qri)?; + encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?; } // Encode diagnostics diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index fdaa13e7fd1..ec6d190b8bd 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -974,4 +974,7 @@ impl_load_from_cache!( BorrowCheck => borrowck, MirBorrowCheck => mir_borrowck, MirConstQualif => mir_const_qualif, + SymbolName => def_symbol_name, + ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static, + ContainsExternIndicator => contains_extern_indicator, ); diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 05aab27dc2a..4f733b8f68a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -356,6 +356,8 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Returns the closure kind for this closure; only usable outside /// of an inference context, because in that context we know that /// there are no type variables. + /// + /// If you have an inference context, use `infcx.closure_kind()`. pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind { self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() } @@ -363,6 +365,8 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Extracts the signature from the closure; only usable outside /// of an inference context, because in that context we know that /// there are no type variables. + /// + /// If you have an inference context, use `infcx.closure_sig()`. pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { match self.closure_sig_ty(def_id, tcx).sty { ty::TyFnPtr(sig) => sig, @@ -646,6 +650,17 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { pub struct Binder<T>(pub T); impl<T> Binder<T> { + /// Wraps `value` in a binder, asserting that `value` does not + /// contain any bound regions that would be bound by the + /// binder. This is commonly used to 'inject' a value T into a + /// different binding level. + pub fn dummy<'tcx>(value: T) -> Binder<T> + where T: TypeFoldable<'tcx> + { + assert!(!value.has_escaping_regions()); + Binder(value) + } + /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// debruijn indices and the like. It is usually better to @@ -700,6 +715,32 @@ impl<T> Binder<T> { Some(self.skip_binder().clone()) } } + + /// Given two things that have the same binder level, + /// and an operation that wraps on their contents, execute the operation + /// and then wrap its result. + /// + /// `f` should consider bound regions at depth 1 to be free, and + /// anything it produces with bound regions at depth 1 will be + /// bound in the resulting return value. + pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R> + where F: FnOnce(T, U) -> R + { + ty::Binder(f(self.0, u.0)) + } + + /// Split the contents into two things that share the same binder + /// level as the original, returning two distinct binders. + /// + /// `f` should consider bound regions at depth 1 to be free, and + /// anything it produces with bound regions at depth 1 will be + /// bound in the resulting return values. + pub fn split<U,V,F>(self, f: F) -> (Binder<U>, Binder<V>) + where F: FnOnce(T) -> (U, V) + { + let (u, v) = f(self.0); + (ty::Binder(u), ty::Binder(v)) + } } /// Represents the projection of an associated type. In explicit UFCS @@ -799,6 +840,9 @@ impl<'tcx> PolyFnSig<'tcx> { pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } + pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice<Ty<'tcx>>> { + self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) + } pub fn output(&self) -> ty::Binder<Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output().clone()) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b1e9bc7e47c..b0f61e9a191 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1069,7 +1069,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, time(time_passes, "MIR borrow checking", - || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id) }); + || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id); }); time(time_passes, "MIR effect checking", diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index ceb94f27dc3..2c33f805203 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -27,10 +27,21 @@ impl StyledBuffer { } fn replace_tabs(&mut self) { - for line in self.text.iter_mut() { - for c in line.iter_mut() { + for (line_pos, line) in self.text.iter_mut().enumerate() { + let mut tab_pos = vec![]; + for (pos, c) in line.iter().enumerate() { if *c == '\t' { - *c = ' '; + tab_pos.push(pos); + } + } + // start with the tabs at the end of the line to replace them with 4 space chars + for pos in tab_pos.iter().rev() { + assert_eq!(line.remove(*pos), '\t'); + // fix the position of the style to match up after replacing the tabs + let s = self.styles[line_pos].remove(*pos); + for _ in 0..4 { + line.insert(*pos, ' '); + self.styles[line_pos].insert(*pos, s); } } } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 722d0cad238..71b15643cbc 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -47,9 +47,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { let mut hasher = StableHasher::new(); hcx.while_hashing_hir_bodies(true, |hcx| { - hcx.while_hashing_spans(false, |hcx| { - body.hash_stable(hcx, &mut hasher); - }); + body.hash_stable(hcx, &mut hasher); }); hasher.finish() diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index eb2bcfc93c5..3be99e97223 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -273,25 +273,23 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { let lo = BytePos::decode(self)?; let hi = BytePos::decode(self)?; + if lo == BytePos(0) && hi == BytePos(0) { + // Don't try to rebase DUMMY_SP. Otherwise it will look like a valid + // Span again. + return Ok(DUMMY_SP) + } + + if hi < lo { + // Consistently map invalid spans to DUMMY_SP. + return Ok(DUMMY_SP) + } + let sess = if let Some(sess) = self.sess { sess } else { bug!("Cannot decode Span without Session.") }; - let (lo, hi) = if lo > hi { - // Currently macro expansion sometimes produces invalid Span values - // where lo > hi. In order not to crash the compiler when trying to - // translate these values, let's transform them into something we - // can handle (and which will produce useful debug locations at - // least some of the time). - // This workaround is only necessary as long as macro expansion is - // not fixed. FIXME(#23480) - (lo, lo) - } else { - (lo, hi) - }; - let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap()); let filemap = { // Optimize for the case that most spans within a translated item @@ -321,6 +319,16 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { } }; + // Make sure our binary search above is correct. + debug_assert!(lo >= filemap.original_start_pos && + lo <= filemap.original_end_pos); + + if hi < filemap.original_start_pos || hi > filemap.original_end_pos { + // `hi` points to a different FileMap than `lo` which is invalid. + // Again, map invalid Spans to DUMMY_SP. + return Ok(DUMMY_SP) + } + let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos; let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 446aba3d3d7..97d8a677fe8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -12,12 +12,14 @@ use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::hir::map::definitions::DefPathData; use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Local, Location, Place}; use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind}; +use rustc::mir::ClosureRegionRequirements; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_set::{self, IdxSetBuf}; @@ -36,6 +38,9 @@ use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveOutIndex, MovePathIndex}; use util::borrowck_errors::{BorrowckErrors, Origin}; +use std::fmt; +use std::iter; + use self::MutateMode::{JustWrite, WriteAndRead}; pub(crate) mod nll; @@ -47,7 +52,10 @@ pub fn provide(providers: &mut Providers) { }; } -fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { +fn mir_borrowck<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Option<ClosureRegionRequirements> { let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); @@ -55,21 +63,23 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.borrowck_mode.use_mir() && !tcx.sess.opts.debugging_opts.nll } { - return; + return None; } - tcx.infer_ctxt().enter(|infcx| { + let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { let input_mir: &Mir = &input_mir.borrow(); - do_mir_borrowck(&infcx, input_mir, def_id); + do_mir_borrowck(&infcx, input_mir, def_id) }); debug!("mir_borrowck done"); + + opt_closure_req } fn do_mir_borrowck<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, input_mir: &Mir<'gcx>, def_id: DefId, -) { +) -> Option<ClosureRegionRequirements> { let tcx = infcx.tcx; let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); @@ -87,7 +97,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mir = &mut mir; // Replace all regions with fresh inference variables. - Some(nll::replace_regions_in_mir(infcx, def_id, mir)) + Some(nll::replace_regions_in_mir(infcx, def_id, param_env, mir)) }; let mir = &mir; @@ -128,6 +138,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( move_data: move_data, param_env: param_env, }; + let body_id = match tcx.def_key(def_id).disambiguated_data.data { + DefPathData::StructCtor | + DefPathData::EnumVariant(_) => None, + _ => Some(tcx.hir.body_owned_by(id)) + }; + let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let mut flow_inits = FlowInProgress::new(do_dataflow( tcx, @@ -167,8 +183,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( )); // If we are in non-lexical mode, compute the non-lexical lifetimes. - let opt_regioncx = if let Some(free_regions) = free_regions { - Some(nll::compute_regions( + let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions { + let (regioncx, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, @@ -176,10 +192,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( param_env, &mut flow_inits, &mdpe.move_data, - )) + ); + (Some(regioncx), opt_closure_req) } else { assert!(!tcx.sess.opts.debugging_opts.nll); - None + (None, None) }; let flow_inits = flow_inits; // remove mut @@ -189,6 +206,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( node_id: id, move_data: &mdpe.move_data, param_env: param_env, + locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) { + hir::BodyOwnerKind::Const | + hir::BodyOwnerKind::Static(_) => false, + hir::BodyOwnerKind::Fn => true, + }, storage_dead_or_drop_error_reported: FxHashSet(), }; @@ -198,7 +220,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - Borrows::new(tcx, mir, opt_regioncx), + Borrows::new(tcx, mir, opt_regioncx, def_id, body_id), |bd, i| bd.location(i), )); @@ -211,6 +233,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( ); mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer + + opt_closure_req } #[allow(dead_code)] @@ -220,6 +244,13 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { node_id: ast::NodeId, move_data: &'cx MoveData<'tcx>, param_env: ParamEnv<'gcx>, + /// This keeps track of whether local variables are free-ed when the function + /// exits even without a `StorageDead`, which appears to be the case for + /// constants. + /// + /// I'm not sure this is the right approach - @eddyb could you try and + /// figure this out? + locals_are_invalidated_at_exit: bool, /// This field keeps track of when storage dead or drop errors are reported /// in order to stop duplicate error reporting and identify the conditions required /// for a "temporary value dropped here while still borrowed" error. See #45360. @@ -306,8 +337,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { - let summary = flow_state.summary(); - debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, summary); + debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, flow_state); } fn visit_statement_entry( @@ -316,12 +346,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx stmt: &Statement<'tcx>, flow_state: &Self::FlowState, ) { - let summary = flow_state.summary(); debug!( "MirBorrowckCtxt::process_statement({:?}, {:?}): {}", location, stmt, - summary + flow_state ); let span = stmt.source_info.span; match stmt.kind { @@ -423,12 +452,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx flow_state: &Self::FlowState, ) { let loc = location; - let summary = flow_state.summary(); debug!( "MirBorrowckCtxt::process_terminator({:?}, {:?}): {}", location, term, - summary + flow_state ); let span = term.source_info.span; match term.kind { @@ -540,14 +568,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx if self.place_is_invalidated_at_exit(&borrow.place) { debug!("borrow conflicts at exit {:?}", borrow); - let borrow_span = self.mir.source_info(borrow.location).span; // FIXME: should be talking about the region lifetime instead // of just a span here. let end_span = domain.opt_region_end_span(&borrow.region); self.report_borrowed_value_does_not_live_long_enough( ContextKind::StorageDead.new(loc), - (&borrow.place, borrow_span), + (&borrow.place, end_span.unwrap_or(span)), end_span, ) } @@ -641,8 +668,9 @@ enum WriteKind { /// - Take flow state into consideration in `is_assignable()` for local variables #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum LocalMutationIsAllowed { + Move, Yes, - No, + No } #[derive(Copy, Clone)] @@ -710,7 +738,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, (sd, place_span.0), flow_state, - |this, _index, borrow, common_prefix| match (rw, borrow.kind) { + |this, _index, borrow| match (rw, borrow.kind) { (Read(_), BorrowKind::Shared) => Control::Continue, (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => { match kind { @@ -727,7 +755,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { error_reported = true; this.report_conflicting_borrow( context, - common_prefix, place_span, bk, &borrow, @@ -748,7 +775,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { error_reported = true; this.report_conflicting_borrow( context, - common_prefix, place_span, bk, &borrow, @@ -934,7 +960,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, (place, span), (Deep, Write(WriteKind::Move)), - LocalMutationIsAllowed::Yes, + LocalMutationIsAllowed::Move, flow_state, ); @@ -952,14 +978,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Returns whether a borrow of this place is invalidated when the function /// exits - fn place_is_invalidated_at_exit(&self, place: &Place<'tcx>) -> bool { + fn place_is_invalidated_at_exit(&mut self, place: &Place<'tcx>) -> bool { debug!("place_is_invalidated_at_exit({:?})", place); let root_place = self.prefixes(place, PrefixSet::All).last().unwrap(); // FIXME(nll-rfc#40): do more precise destructor tracking here. For now // we just know that all locals are dropped at function exit (otherwise // we'll have a memory leak) and assume that all statics have a destructor. - let (might_be_alive, will_be_dropped) = match root_place { + // + // FIXME: allow thread-locals to borrow other thread locals? + let (might_be_alive, will_be_dropped, local) = match root_place { Place::Static(statik) => { // Thread-locals might be dropped after the function exits, but // "true" statics will never be. @@ -968,12 +996,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .iter() .any(|attr| attr.check_name("thread_local")); - (true, is_thread_local) + (true, is_thread_local, None) } - Place::Local(_) => { + Place::Local(local) => { // Locals are always dropped at function exit, and if they // have a destructor it would've been called already. - (false, true) + (false, self.locals_are_invalidated_at_exit, Some(*local)) } Place::Projection(..) => { bug!("root of {:?} is a projection ({:?})?", place, root_place) @@ -996,8 +1024,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { PrefixSet::Shallow }; - self.prefixes(place, prefix_set) - .any(|prefix| prefix == root_place) + let result = + self.prefixes(place, prefix_set).any(|prefix| prefix == root_place); + + if result { + if let Some(local) = local { + if let Some(_) = self.storage_dead_or_drop_error_reported.replace(local) { + debug!("place_is_invalidated_at_exit({:?}) - suppressed", place); + return false; + } + } + } + + result } } @@ -1343,7 +1382,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { - LocalMutationIsAllowed::Yes => Ok(()), + LocalMutationIsAllowed::Yes | + LocalMutationIsAllowed::Move => Ok(()), LocalMutationIsAllowed::No => Err(place), }, Mutability::Mut => Ok(()), @@ -1368,10 +1408,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Mutably borrowed data is mutable, but only if we have a // unique path to the `&mut` hir::MutMutable => { - if self.is_upvar_field_projection(&proj.base).is_some() { - self.is_mutable(&proj.base, is_local_mutation_allowed) - } else { - self.is_unique(&proj.base) + match self.is_upvar_field_projection(&proj.base) { + Some(field) if { + self.mir.upvar_decls[field.index()].by_ref + } => { + self.is_mutable(&proj.base, + is_local_mutation_allowed) + } + _ => self.is_unique(&proj.base) } } } @@ -1387,7 +1431,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // `Box<T>` owns its content, so mutable if its location is mutable _ if base_ty.is_box() => { - self.is_mutable(&proj.base, LocalMutationIsAllowed::No) + self.is_mutable(&proj.base, is_local_mutation_allowed) } // Deref should only be for reference, pointers or boxes _ => bug!("Deref of unexpected type: {:?}", base_ty), @@ -1404,14 +1448,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Some(field) = field_projection { let decl = &self.mir.upvar_decls[field.index()]; - - return match decl.mutability { - Mutability::Mut => self.is_unique(&proj.base), - Mutability::Not => Err(place), + debug!("decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}", + decl, is_local_mutation_allowed, place); + return match (decl.mutability, is_local_mutation_allowed) { + (Mutability::Not, LocalMutationIsAllowed::No) | + (Mutability::Not, LocalMutationIsAllowed::Yes) => Err(place), + (Mutability::Not, LocalMutationIsAllowed::Move) | + (Mutability::Mut, _) => self.is_unique(&proj.base), }; } - self.is_mutable(&proj.base, LocalMutationIsAllowed::No) + self.is_mutable(&proj.base, is_local_mutation_allowed) } } } @@ -1425,9 +1472,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Local variables are unique Ok(()) } - Place::Static(..) => { - // Static variables are not - Err(place) + Place::Static(ref static_) => { + if !self.tcx.is_static_mut(static_.def_id) { + Err(place) + } else { + Ok(()) + } } Place::Projection(ref proj) => { match proj.elem { @@ -1478,7 +1528,350 @@ enum NoMovePathFound { ReachedStatic, } +/// The degree of overlap between 2 places for borrow-checking. +enum Overlap { + /// The places might partially overlap - in this case, we give + /// up and say that they might conflict. This occurs when + /// different fields of a union are borrowed. For example, + /// if `u` is a union, we have no way of telling how disjoint + /// `u.a.x` and `a.b.y` are. + Arbitrary, + /// The places have the same type, and are either completely disjoint + /// or equal - i.e. they can't "partially" overlap as can occur with + /// unions. This is the "base case" on which we recur for extensions + /// of the place. + EqualOrDisjoint, + /// The places are disjoint, so we know all extensions of them + /// will also be disjoint. + Disjoint, +} + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + // Given that the bases of `elem1` and `elem2` are always either equal + // or disjoint (and have the same type!), return the overlap situation + // between `elem1` and `elem2`. + fn place_element_conflict(&self, + elem1: &Place<'tcx>, + elem2: &Place<'tcx>) + -> Overlap + { + match (elem1, elem2) { + (Place::Local(l1), Place::Local(l2)) => { + if l1 == l2 { + // the same local - base case, equal + debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL"); + Overlap::EqualOrDisjoint + } else { + // different locals - base case, disjoint + debug!("place_element_conflict: DISJOINT-LOCAL"); + Overlap::Disjoint + } + } + (Place::Static(..), Place::Static(..)) => { + // Borrows of statics do not have to be tracked here. + debug!("place_element_conflict: IGNORED-STATIC"); + Overlap::Disjoint + } + (Place::Local(_), Place::Static(_)) | + (Place::Static(_), Place::Local(_)) => { + debug!("place_element_conflict: DISJOINT-STATIC-LOCAL"); + Overlap::Disjoint + } + (Place::Projection(pi1), Place::Projection(pi2)) => { + match (&pi1.elem, &pi2.elem) { + (ProjectionElem::Deref, ProjectionElem::Deref) => { + // derefs (e.g. `*x` vs. `*x`) - recur. + debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF"); + Overlap::EqualOrDisjoint + } + (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => { + if f1 == f2 { + // same field (e.g. `a.y` vs. `a.y`) - recur. + debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); + Overlap::EqualOrDisjoint + } else { + let ty = pi1.base.ty(self.mir, self.tcx).to_ty(self.tcx); + match ty.sty { + ty::TyAdt(def, _) if def.is_union() => { + // Different fields of a union, we are basically stuck. + debug!("place_element_conflict: STUCK-UNION"); + Overlap::Arbitrary + } + _ => { + // Different fields of a struct (`a.x` vs. `a.y`). Disjoint! + debug!("place_element_conflict: DISJOINT-FIELD"); + Overlap::Disjoint + } + } + } + } + (ProjectionElem::Downcast(_, v1), ProjectionElem::Downcast(_, v2)) => { + // different variants are treated as having disjoint fields, + // even if they occupy the same "space", because it's + // impossible for 2 variants of the same enum to exist + // (and therefore, to be borrowed) at the same time. + // + // Note that this is different from unions - we *do* allow + // this code to compile: + // + // ``` + // fn foo(x: &mut Result<i32, i32>) { + // let mut v = None; + // if let Ok(ref mut a) = *x { + // v = Some(a); + // } + // // here, you would *think* that the + // // *entirety* of `x` would be borrowed, + // // but in fact only the `Ok` variant is, + // // so the `Err` variant is *entirely free*: + // if let Err(ref mut a) = *x { + // v = Some(a); + // } + // drop(v); + // } + // ``` + if v1 == v2 { + debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); + Overlap::EqualOrDisjoint + } else { + debug!("place_element_conflict: DISJOINT-FIELD"); + Overlap::Disjoint + } + } + (ProjectionElem::Index(..), ProjectionElem::Index(..)) | + (ProjectionElem::Index(..), ProjectionElem::ConstantIndex { .. }) | + (ProjectionElem::Index(..), ProjectionElem::Subslice { .. }) | + (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Index(..)) | + (ProjectionElem::ConstantIndex { .. }, ProjectionElem::ConstantIndex { .. }) | + (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Subslice { .. }) | + (ProjectionElem::Subslice { .. }, ProjectionElem::Index(..)) | + (ProjectionElem::Subslice { .. }, ProjectionElem::ConstantIndex { .. }) | + (ProjectionElem::Subslice { .. }, ProjectionElem::Subslice { .. }) => { + // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint + // (if the indexes differ) or equal (if they are the same), so this + // is the recursive case that gives "equal *or* disjoint" its meaning. + // + // Note that by construction, MIR at borrowck can't subdivide + // `Subslice` accesses (e.g. `a[2..3][i]` will never be present) - they + // are only present in slice patterns, and we "merge together" nested + // slice patterns. That means we don't have to think about these. It's + // probably a good idea to assert this somewhere, but I'm too lazy. + // + // FIXME(#8636) we might want to return Disjoint if + // both projections are constant and disjoint. + debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY"); + Overlap::EqualOrDisjoint + } + + (ProjectionElem::Deref, _) | + (ProjectionElem::Field(..), _) | + (ProjectionElem::Index(..), _) | + (ProjectionElem::ConstantIndex { .. }, _) | + (ProjectionElem::Subslice { .. }, _) | + (ProjectionElem::Downcast(..), _) => { + bug!("mismatched projections in place_element_conflict: {:?} and {:?}", + + elem1, elem2) + } + } + } + (Place::Projection(_), _) | + (_, Place::Projection(_)) => { + bug!("unexpected elements in place_element_conflict: {:?} and {:?}", + elem1, elem2) + } + } + } + fn borrow_conflicts_with_place(&mut self, + borrow: &BorrowData<'tcx>, + place: &Place<'tcx>, + access: ShallowOrDeep) + -> bool + { + debug!("borrow_conflicts_with_place({:?},{:?},{:?})", borrow, place, access); + + // Return all the prefixes of `place` in reverse order, including + // downcasts. + fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> + { + let mut result = vec![]; + let mut place = place; + loop { + result.push(place); + match place { + Place::Projection(interior) => { + place = &interior.base; + } + Place::Local(_) | Place::Static(_) => { + result.reverse(); + return result; + } + } + } + } + + let borrow_components = place_elements(&borrow.place); + let access_components = place_elements(place); + debug!("borrow_conflicts_with_place: components {:?} / {:?}", + borrow_components, access_components); + + let borrow_components = borrow_components.into_iter() + .map(Some).chain(iter::repeat(None)); + let access_components = access_components.into_iter() + .map(Some).chain(iter::repeat(None)); + // The borrowck rules for proving disjointness are applied from the "root" of the + // borrow forwards, iterating over "similar" projections in lockstep until + // we can prove overlap one way or another. Essentially, we treat `Overlap` as + // a monoid and report a conflict if the product ends up not being `Disjoint`. + // + // At each step, if we didn't run out of borrow or place, we know that our elements + // have the same type, and that they only overlap if they are the identical. + // + // For example, if we are comparing these: + // BORROW: (*x1[2].y).z.a + // ACCESS: (*x1[i].y).w.b + // + // Then our steps are: + // x1 | x1 -- places are the same + // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) + // x1[2].y | x1[i].y -- equal or disjoint + // *x1[2].y | *x1[i].y -- equal or disjoint + // (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! + // + // Because `zip` does potentially bad things to the iterator inside, this loop + // also handles the case where the access might be a *prefix* of the borrow, e.g. + // + // BORROW: (*x1[2].y).z.a + // ACCESS: x1[i].y + // + // Then our steps are: + // x1 | x1 -- places are the same + // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) + // x1[2].y | x1[i].y -- equal or disjoint + // + // -- here we run out of access - the borrow can access a part of it. If this + // is a full deep access, then we *know* the borrow conflicts with it. However, + // if the access is shallow, then we can proceed: + // + // x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we + // are disjoint + // + // Our invariant is, that at each step of the iteration: + // - If we didn't run out of access to match, our borrow and access are comparable + // and either equal or disjoint. + // - If we did run out of accesss, the borrow can access a part of it. + for (borrow_c, access_c) in borrow_components.zip(access_components) { + // loop invariant: borrow_c is always either equal to access_c or disjoint from it. + debug!("borrow_conflicts_with_place: {:?} vs. {:?}", borrow_c, access_c); + match (borrow_c, access_c) { + (None, _) => { + // If we didn't run out of access, the borrow can access all of our + // place (e.g. a borrow of `a.b` with an access to `a.b.c`), + // so we have a conflict. + // + // If we did, then we still know that the borrow can access a *part* + // of our place that our access cares about (a borrow of `a.b.c` + // with an access to `a.b`), so we still have a conflict. + // + // FIXME: Differs from AST-borrowck; includes drive-by fix + // to #38899. Will probably need back-compat mode flag. + debug!("borrow_conflict_with_place: full borrow, CONFLICT"); + return true; + } + (Some(borrow_c), None) => { + // We know that the borrow can access a part of our place. This + // is a conflict if that is a part our access cares about. + + let (base, elem) = match borrow_c { + Place::Projection(box Projection { base, elem }) => (base, elem), + _ => bug!("place has no base?") + }; + let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); + + match (elem, &base_ty.sty, access) { + (_, _, Shallow(Some(ArtificialField::Discriminant))) | + (_, _, Shallow(Some(ArtificialField::ArrayLength))) => { + // The discriminant and array length are like + // additional fields on the type; they do not + // overlap any existing data there. Furthermore, + // they cannot actually be a prefix of any + // borrowed place (at least in MIR as it is + // currently.) + // + // e.g. a (mutable) borrow of `a[5]` while we read the + // array length of `a`. + debug!("borrow_conflicts_with_place: implicit field"); + return false; + } + + (ProjectionElem::Deref, _, Shallow(None)) => { + // e.g. a borrow of `*x.y` while we shallowly access `x.y` or some + // prefix thereof - the shallow access can't touch anything behind + // the pointer. + debug!("borrow_conflicts_with_place: shallow access behind ptr"); + return false; + } + (ProjectionElem::Deref, ty::TyRef(_, ty::TypeAndMut { + ty: _, mutbl: hir::MutImmutable + }), _) => { + // the borrow goes through a dereference of a shared reference. + // + // I'm not sure why we are tracking these borrows - shared + // references can *always* be aliased, which means the + // permission check already account for this borrow. + debug!("borrow_conflicts_with_place: behind a shared ref"); + return false; + } + + (ProjectionElem::Deref, _, Deep) | + (ProjectionElem::Field { .. }, _, _) | + (ProjectionElem::Index { ..}, _, _) | + (ProjectionElem::ConstantIndex { .. }, _, _) | + (ProjectionElem::Subslice { .. }, _, _) | + (ProjectionElem::Downcast { .. }, _, _) => { + // Recursive case. This can still be disjoint on a + // further iteration if this a shallow access and + // there's a deref later on, e.g. a borrow + // of `*x.y` while accessing `x`. + } + } + } + (Some(borrow_c), Some(access_c)) => { + match self.place_element_conflict(&borrow_c, access_c) { + Overlap::Arbitrary => { + // We have encountered different fields of potentially + // the same union - the borrow now partially overlaps. + // + // There is no *easy* way of comparing the fields + // further on, because they might have different types + // (e.g. borrows of `u.a.0` and `u.b.y` where `.0` and + // `.y` come from different structs). + // + // We could try to do some things here - e.g. count + // dereferences - but that's probably not a good + // idea, at least for now, so just give up and + // report a conflict. This is unsafe code anyway so + // the user could always use raw pointers. + debug!("borrow_conflicts_with_place: arbitrary -> conflict"); + return true; + } + Overlap::EqualOrDisjoint => { + // This is the recursive case - proceed to the next element. + } + Overlap::Disjoint => { + // We have proven the borrow disjoint - further + // projections will remain disjoint. + debug!("borrow_conflicts_with_place: disjoint"); + return false; + } + } + + } + } + } + unreachable!("iter::repeat returned None") + } + fn each_borrow_involving_path<F>( &mut self, _context: Context, @@ -1486,7 +1879,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { flow_state: &InProgress<'cx, 'gcx, 'tcx>, mut op: F, ) where - F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Place<'tcx>) -> Control, + F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>) -> Control, { let (access, place) = access_place; @@ -1501,47 +1894,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { 'next_borrow: for i in flow_state.borrows.elems_incoming() { let borrowed = &data[i]; - // Is `place` (or a prefix of it) already borrowed? If - // so, that's relevant. - // - // FIXME: Differs from AST-borrowck; includes drive-by fix - // to #38899. Will probably need back-compat mode flag. - for accessed_prefix in self.prefixes(place, PrefixSet::All) { - if *accessed_prefix == borrowed.place { - // FIXME: pass in enum describing case we are in? - let ctrl = op(self, i, borrowed, accessed_prefix); - if ctrl == Control::Break { - return; - } - } - } - - // Is `place` a prefix (modulo access type) of the - // `borrowed.place`? If so, that's relevant. - - let prefix_kind = match access { - Shallow(Some(ArtificialField::Discriminant)) | - Shallow(Some(ArtificialField::ArrayLength)) => { - // The discriminant and array length are like - // additional fields on the type; they do not - // overlap any existing data there. Furthermore, - // they cannot actually be a prefix of any - // borrowed place (at least in MIR as it is - // currently.) - continue 'next_borrow; - } - Shallow(None) => PrefixSet::Shallow, - Deep => PrefixSet::Supporting, - }; - - for borrowed_prefix in self.prefixes(&borrowed.place, prefix_kind) { - if borrowed_prefix == place { - // FIXME: pass in enum describing case we are in? - let ctrl = op(self, i, borrowed, borrowed_prefix); - if ctrl == Control::Break { - return; - } - } + if self.borrow_conflicts_with_place(borrowed, place, access) { + let ctrl = op(self, i, borrowed); + if ctrl == Control::Break { return; } } } } @@ -1595,6 +1950,7 @@ mod prefixes { } #[derive(Copy, Clone, PartialEq, Eq, Debug)] + #[allow(dead_code)] pub(super) enum PrefixSet { /// Doesn't stop until it returns the base case (a Local or /// Static prefix). @@ -1907,17 +2263,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn report_conflicting_borrow( &mut self, context: Context, - common_prefix: &Place<'tcx>, (place, span): (&Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData, end_issued_loan_span: Option<Span>, ) { - use self::prefixes::IsPrefixOf; - - assert!(common_prefix.is_prefix_of(place)); - assert!(common_prefix.is_prefix_of(&issued_borrow.place)); - let issued_span = self.retrieve_borrow_span(issued_borrow); let new_closure_span = self.find_closure_span(span, context.loc); @@ -2373,8 +2723,10 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> { xform_move_outs(&mut self.move_outs); xform_ever_inits(&mut self.ever_inits); } +} - fn summary(&self) -> String { +impl<'b, 'gcx, 'tcx> fmt::Display for InProgress<'b, 'gcx, 'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut s = String::new(); s.push_str("borrows in effect: ["); @@ -2451,7 +2803,7 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> { }); s.push_str("]"); - return s; + fmt::Display::fmt(&s, fmt) } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 804f5e26875..4ff299efb95 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -9,11 +9,12 @@ // except according to those terms. use rustc::hir::def_id::DefId; -use rustc::mir::Mir; +use rustc::mir::{ClosureRegionRequirements, Mir}; use rustc::infer::InferCtxt; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use std::collections::BTreeSet; +use std::io; use transform::MirSource; use transform::type_check; use util::liveness::{self, LivenessMode, LivenessResult, LocalSet}; @@ -22,6 +23,7 @@ use dataflow::MaybeInitializedLvals; use dataflow::move_paths::MoveData; use util as mir_util; +use util::pretty::{self, ALIGN}; use self::mir_util::PassWhere; mod constraint_generation; @@ -35,20 +37,26 @@ use self::region_infer::RegionInferenceContext; mod renumber; /// Rewrites the regions in the MIR to use NLL variables, also -/// scraping out the set of free regions (e.g., region parameters) +/// scraping out the set of universal regions (e.g., region parameters) /// declared on the function. That set will need to be given to /// `compute_regions`. pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>( infcx: &InferCtxt<'cx, 'gcx, 'tcx>, def_id: DefId, + param_env: ty::ParamEnv<'tcx>, mir: &mut Mir<'tcx>, ) -> UniversalRegions<'tcx> { - // Compute named region information. - let universal_regions = universal_regions::universal_regions(infcx, def_id); + debug!("replace_regions_in_mir(def_id={:?})", def_id); - // Replace all regions with fresh inference variables. + // Compute named region information. This also renumbers the inputs/outputs. + let universal_regions = UniversalRegions::new(infcx, def_id, param_env); + + // Replace all remaining regions with fresh inference variables. renumber::renumber_mir(infcx, &universal_regions, mir); + let source = MirSource::item(def_id); + mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, mir, |_, _| Ok(())); + universal_regions } @@ -63,7 +71,10 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( param_env: ty::ParamEnv<'gcx>, flow_inits: &mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, -) -> RegionInferenceContext<'tcx> { +) -> ( + RegionInferenceContext<'tcx>, + Option<ClosureRegionRequirements>, +) { // Run the MIR type-checker. let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap(); let constraint_sets = &type_check::type_check(infcx, mir_node_id, param_env, mir); @@ -71,13 +82,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( // Create the region inference context, taking ownership of the region inference // data that was contained in `infcx`. let var_origins = infcx.take_region_var_origins(); - let mut regioncx = RegionInferenceContext::new(var_origins, &universal_regions, mir); - subtype_constraint_generation::generate( - &mut regioncx, - &universal_regions, - mir, - constraint_sets, - ); + let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir); + subtype_constraint_generation::generate(&mut regioncx, mir, constraint_sets); // Compute what is live where. let liveness = &LivenessResults { @@ -110,13 +116,24 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( ); // Solve the region constraints. - regioncx.solve(infcx, &mir); + let closure_region_requirements = regioncx.solve(infcx, &mir, def_id); // Dump MIR results into a file, if that is enabled. This let us - // write unit-tests. - dump_mir_results(infcx, liveness, MirSource::item(def_id), &mir, ®ioncx); + // write unit-tests, as well as helping with debugging. + dump_mir_results( + infcx, + liveness, + MirSource::item(def_id), + &mir, + ®ioncx, + &closure_region_requirements, + ); - regioncx + // We also have a `#[rustc_nll]` annotation that causes us to dump + // information + dump_annotation(infcx, &mir, def_id, ®ioncx, &closure_region_requirements); + + (regioncx, closure_region_requirements) } struct LivenessResults { @@ -130,6 +147,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, + closure_region_requirements: &Option<ClosureRegionRequirements>, ) { if !mir_util::dump_enabled(infcx.tcx, "nll", source) { return; @@ -164,9 +182,17 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, mir, |pass_where, out| { match pass_where { // Before the CFG, dump out the values for each region variable. - PassWhere::BeforeCFG => for region in regioncx.regions() { - writeln!(out, "| {:?}: {}", region, regioncx.region_value_str(region))?; - }, + PassWhere::BeforeCFG => { + regioncx.dump_mir(out)?; + + if let Some(closure_region_requirements) = closure_region_requirements { + writeln!(out, "|")?; + writeln!(out, "| Free Region Constraints")?; + for_each_region_constraint(closure_region_requirements, &mut |msg| { + writeln!(out, "| {}", msg) + })?; + } + } // Before each basic block, dump out the values // that are live on entry to the basic block. @@ -180,19 +206,96 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( ®ular_liveness_per_location[&location], &drop_liveness_per_location[&location], ); - writeln!(out, " | Live variables at {:?}: {}", location, s)?; + writeln!( + out, + "{:ALIGN$} | Live variables on entry to {:?}: {}", + "", + location, + s, + ALIGN = ALIGN + )?; } PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {} } Ok(()) }); + + // Also dump the inference graph constraints as a graphviz file. + let _: io::Result<()> = do catch { + let mut file = + pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?; + regioncx.dump_graphviz(&mut file) + }; +} + +fn dump_annotation<'a, 'gcx, 'tcx>( + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + mir_def_id: DefId, + regioncx: &RegionInferenceContext, + closure_region_requirements: &Option<ClosureRegionRequirements>, +) { + let tcx = infcx.tcx; + let base_def_id = tcx.closure_base_def_id(mir_def_id); + if !tcx.has_attr(base_def_id, "rustc_regions") { + return; + } + + // When the enclosing function is tagged with `#[rustc_regions]`, + // we dump out various bits of state as warnings. This is useful + // for verifying that the compiler is behaving as expected. These + // warnings focus on the closure region requirements -- for + // viewing the intraprocedural state, the -Zdump-mir output is + // better. + + if let Some(closure_region_requirements) = closure_region_requirements { + let mut err = tcx.sess + .diagnostic() + .span_note_diag(mir.span, "External requirements"); + + regioncx.annotate(&mut err); + + err.note(&format!( + "number of external vids: {}", + closure_region_requirements.num_external_vids + )); + + // Dump the region constraints we are imposing *between* those + // newly created variables. + for_each_region_constraint(closure_region_requirements, &mut |msg| { + err.note(msg); + Ok(()) + }).unwrap(); + + err.emit(); + } else { + let mut err = tcx.sess + .diagnostic() + .span_note_diag(mir.span, "No external requirements"); + regioncx.annotate(&mut err); + err.emit(); + } +} + +fn for_each_region_constraint( + closure_region_requirements: &ClosureRegionRequirements, + with_msg: &mut FnMut(&str) -> io::Result<()>, +) -> io::Result<()> { + for req in &closure_region_requirements.outlives_requirements { + with_msg(&format!( + "where {:?}: {:?}", + req.free_region, + req.outlived_free_region, + ))?; + } + Ok(()) } /// Right now, we piggy back on the `ReVar` to store our NLL inference /// regions. These are indexed with `RegionVid`. This method will /// assert that the region is a `ReVar` and extract its interal index. -/// This is reasonable because in our MIR we replace all free regions +/// This is reasonable because in our MIR we replace all universal regions /// with inference variables. pub trait ToRegionVid { fn to_region_vid(&self) -> RegionVid; diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs new file mode 100644 index 00000000000..906efaef887 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs @@ -0,0 +1,48 @@ +// 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. + +//! As part of the NLL unit tests, you can annotate a function with +//! `#[rustc_regions]`, and we will emit information about the region +//! inference context and -- in particular -- the external constraints +//! that this region imposes on others. The methods in this file +//! handle the part about dumping the inference context internal +//! state. + +use rustc::ty; +use rustc_errors::DiagnosticBuilder; +use super::RegionInferenceContext; + +impl<'gcx, 'tcx> RegionInferenceContext<'tcx> { + /// Write out our state into the `.mir` files. + pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) { + match self.universal_regions.defining_ty.sty { + ty::TyClosure(def_id, substs) => { + err.note(&format!( + "defining type: {:?} with closure substs {:#?}", + def_id, + &substs.substs[..] + )); + } + ty::TyFnDef(def_id, substs) => { + err.note(&format!( + "defining type: {:?} with substs {:#?}", + def_id, + &substs[..] + )); + } + _ => { + err.note(&format!( + "defining type: {:?}", + self.universal_regions.defining_ty + )); + } + } + } +} diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs new file mode 100644 index 00000000000..5477308bde9 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -0,0 +1,100 @@ +// 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. + +//! As part of generating the regions, if you enable `-Zdump-mir=nll`, +//! we will generate an annotated copy of the MIR that includes the +//! state of region inference. This code handles emitting the region +//! context internal state. + +use std::io::{self, Write}; +use super::{Constraint, RegionInferenceContext}; + +// Room for "'_#NNNNr" before things get misaligned. +// Easy enough to fix if this ever doesn't seem like +// enough. +const REGION_WIDTH: usize = 8; + +impl<'tcx> RegionInferenceContext<'tcx> { + /// Write out our state into the `.mir` files. + pub(crate) fn dump_mir(&self, out: &mut Write) -> io::Result<()> { + writeln!(out, "| Free Region Mapping")?; + + for region in self.regions() { + if self.definitions[region].is_universal { + let classification = self.universal_regions.region_classification(region).unwrap(); + let outlived_by = self.universal_regions.regions_outlived_by(region); + writeln!( + out, + "| {r:rw$} | {c:cw$} | {ob}", + r = format!("{:?}", region), + rw = REGION_WIDTH, + c = format!("{:?}", classification), + cw = 8, // "External" at most + ob = format!("{:?}", outlived_by) + )?; + } + } + + writeln!(out, "|")?; + writeln!(out, "| Inferred Region Values")?; + for region in self.regions() { + writeln!( + out, + "| {r:rw$} | {v}", + r = format!("{:?}", region), + rw = REGION_WIDTH, + v = self.region_value_str(region), + )?; + } + + writeln!(out, "|")?; + writeln!(out, "| Inference Constraints")?; + self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?; + + Ok(()) + } + + /// Debugging aid: Invokes the `with_msg` callback repeatedly with + /// our internal region constraints. These are dumped into the + /// -Zdump-mir file so that we can figure out why the region + /// inference resulted in the values that it did when debugging. + fn for_each_constraint( + &self, + with_msg: &mut FnMut(&str) -> io::Result<()>, + ) -> io::Result<()> { + for region in self.definitions.indices() { + let value = self.region_value_str_from_matrix(&self.liveness_constraints, region); + if value != "{}" { + with_msg(&format!("{:?} live at {}", region, value))?; + } + } + + let mut constraints: Vec<_> = self.constraints.iter().collect(); + constraints.sort(); + for constraint in &constraints { + let Constraint { + sup, + sub, + point, + span, + } = constraint; + with_msg(&format!( + "{:?}: {:?} @ {:?} due to {:?}", + sup, + sub, + point, + span + ))?; + } + + Ok(()) + } +} + diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs new file mode 100644 index 00000000000..7923b159d80 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs @@ -0,0 +1,71 @@ +// Copyright 2014 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. + +//! This module provides linkage between RegionInferenceContext and +//! libgraphviz traits, specialized to attaching borrowck analysis +//! data to rendered labels. + +use dot::{self, IntoCow}; +use rustc_data_structures::indexed_vec::Idx; +use std::borrow::Cow; +use std::io::{self, Write}; +use super::*; + +impl<'tcx> RegionInferenceContext<'tcx> { + /// Write out the region constraint graph. + pub(crate) fn dump_graphviz(&self, mut w: &mut Write) -> io::Result<()> { + dot::render(self, &mut w) + } +} + +impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> { + type Node = RegionVid; + type Edge = Constraint; + + fn graph_id(&'this self) -> dot::Id<'this> { + dot::Id::new(format!("RegionInferenceContext")).unwrap() + } + fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> { + dot::Id::new(format!("r{}", n.index())).unwrap() + } + fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> { + Some(dot::LabelText::LabelStr(Cow::Borrowed("box"))) + } + fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> { + dot::LabelText::LabelStr(format!("{:?}", n).into_cow()) + } + fn edge_label(&'this self, e: &Constraint) -> dot::LabelText<'this> { + dot::LabelText::LabelStr(format!("{:?}", e.point).into_cow()) + } +} + +impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> { + type Node = RegionVid; + type Edge = Constraint; + + fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> { + let vids: Vec<RegionVid> = self.definitions.indices().collect(); + vids.into_cow() + } + fn edges(&'this self) -> dot::Edges<'this, Constraint> { + (&self.constraints[..]).into_cow() + } + + // Render `a: b` as `a <- b`, indicating the flow + // of data during inference. + + fn source(&'this self, edge: &Constraint) -> RegionVid { + edge.sub + } + + fn target(&'this self, edge: &Constraint) -> RegionVid { + edge.sup + } +} diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index d1faaf75a53..b2e2ccc5d0b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -9,12 +9,13 @@ // except according to those terms. use super::universal_regions::UniversalRegions; +use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::infer::RegionVariableOrigin; use rustc::infer::NLLRegionVariableOrigin; +use rustc::infer::RegionVariableOrigin; +use rustc::infer::SubregionOrigin; use rustc::infer::region_constraints::VarOrigins; -use rustc::infer::outlives::free_region_map::FreeRegionMap; -use rustc::mir::{Location, Mir}; +use rustc::mir::{ClosureOutlivesRequirement, ClosureRegionRequirements, Location, Mir}; use rustc::ty::{self, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashSet; @@ -24,6 +25,10 @@ use std::collections::BTreeMap; use std::fmt; use syntax_pos::Span; +mod annotation; +mod dump_mir; +mod graphviz; + pub struct RegionInferenceContext<'tcx> { /// Contains the definition for every region variable. Region /// variables are identified by their index (`RegionVid`). The @@ -52,12 +57,9 @@ pub struct RegionInferenceContext<'tcx> { /// the free regions.) point_indices: BTreeMap<Location, usize>, - /// Number of universally quantified regions. This is used to - /// determine the meaning of the bits in `inferred_values` and - /// friends. - num_universal_regions: usize, - - free_region_map: &'tcx FreeRegionMap<'tcx>, + /// Information about the universally quantified regions in scope + /// on this function and their (known) relations to one another. + universal_regions: UniversalRegions<'tcx>, } struct RegionDefinition<'tcx> { @@ -67,9 +69,15 @@ struct RegionDefinition<'tcx> { /// late-bound-regions). origin: RegionVariableOrigin, - /// If this is a free-region, then this is `Some(X)` where `X` is - /// the name of the region. - name: Option<ty::Region<'tcx>>, + /// True if this is a universally quantified region. This means a + /// lifetime parameter that appears in the function signature (or, + /// in the case of a closure, in the closure environment, which of + /// course is also in the function signature). + is_universal: bool, + + /// If this is 'static or an early-bound region, then this is + /// `Some(X)` where `X` is the name of the region. + external_name: Option<ty::Region<'tcx>>, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -98,11 +106,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// regions defined in `universal_regions`. pub fn new( var_origins: VarOrigins, - universal_regions: &UniversalRegions<'tcx>, + universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, ) -> Self { let num_region_variables = var_origins.len(); - let num_universal_regions = universal_regions.indices.len(); + let num_universal_regions = universal_regions.len(); let mut num_points = 0; let mut point_indices = BTreeMap::new(); @@ -133,11 +141,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { inferred_values: None, constraints: Vec::new(), point_indices, - num_universal_regions, - free_region_map: universal_regions.free_region_map, + universal_regions, }; - result.init_universal_regions(universal_regions); + result.init_universal_regions(); result } @@ -159,25 +166,24 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// R1 = { CFG, R0, R1 } // 'b /// /// Here, R0 represents `'a`, and it contains (a) the entire CFG - /// and (b) any free regions that it outlives, which in this case - /// is just itself. R1 (`'b`) in contrast also outlives `'a` and - /// hence contains R0 and R1. - fn init_universal_regions(&mut self, universal_regions: &UniversalRegions<'tcx>) { - let UniversalRegions { - indices, - free_region_map: _, - } = universal_regions; + /// and (b) any universally quantified regions that it outlives, + /// which in this case is just itself. R1 (`'b`) in contrast also + /// outlives `'a` and hence contains R0 and R1. + fn init_universal_regions(&mut self) { + // Update the names (if any) + for (external_name, variable) in self.universal_regions.named_universal_regions() { + self.definitions[variable].external_name = Some(external_name); + } // For each universally quantified region X: - for (free_region, &variable) in indices { + for variable in self.universal_regions.universal_regions() { // These should be free-region variables. assert!(match self.definitions[variable].origin { RegionVariableOrigin::NLL(NLLRegionVariableOrigin::FreeRegion) => true, _ => false, }); - // Initialize the name and a few other details. - self.definitions[variable].name = Some(free_region); + self.definitions[variable].is_universal = true; // Add all nodes in the CFG to liveness constraints for (_location, point_index) in &self.point_indices { @@ -196,6 +202,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.definitions.indices() } + /// Given a universal region in scope on the MIR, returns the + /// corresponding index. + /// + /// (Panics if `r` is not a registered universal region.) + pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + self.universal_regions.to_region_vid(r) + } + /// Returns true if the region `r` contains the point `p`. /// /// Panics if called before `solve()` executes, @@ -237,19 +251,25 @@ impl<'tcx> RegionInferenceContext<'tcx> { .as_ref() .expect("region values not yet inferred"); + self.region_value_str_from_matrix(inferred_values, r) + } + + fn region_value_str_from_matrix(&self, + matrix: &BitMatrix, + r: RegionVid) -> String { let mut result = String::new(); result.push_str("{"); let mut sep = ""; for &point in self.point_indices.keys() { - if self.region_contains_point_in_matrix(inferred_values, r, point) { + if self.region_contains_point_in_matrix(matrix, r, point) { result.push_str(&format!("{}{:?}", sep, point)); sep = ", "; } } - for fr in (0..self.num_universal_regions).map(RegionVid::new) { - if self.region_contains_region_in_matrix(inferred_values, r, fr) { + for fr in (0..self.universal_regions.len()).map(RegionVid::new) { + if self.region_contains_region_in_matrix(matrix, r, fr) { result.push_str(&format!("{}{:?}", sep, fr)); sep = ", "; } @@ -289,8 +309,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Perform region inference. - pub(super) fn solve(&mut self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) { + pub(super) fn solve( + &mut self, + infcx: &InferCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + mir_def_id: DefId, + ) -> Option<ClosureRegionRequirements> { assert!(self.inferred_values.is_none(), "values already inferred"); + let tcx = infcx.tcx; // Find the minimal regions that can solve the constraints. This is infallible. self.propagate_constraints(mir); @@ -310,57 +336,135 @@ impl<'tcx> RegionInferenceContext<'tcx> { // The universal regions are always found in a prefix of the // full list. - let free_region_definitions = self.definitions + let universal_definitions = self.definitions .iter_enumerated() - .take_while(|(_, fr_definition)| fr_definition.name.is_some()); + .take_while(|(_, fr_definition)| fr_definition.is_universal); + + // Go through each of the universal regions `fr` and check that + // they did not grow too large, accumulating any requirements + // for our caller into the `outlives_requirements` vector. + let mut outlives_requirements = vec![]; + for (fr, _) in universal_definitions { + self.check_universal_region(infcx, fr, &mut outlives_requirements); + } - for (fr, fr_definition) in free_region_definitions { - self.check_free_region(infcx, fr, fr_definition); + // If this is not a closure, then there is no caller to which we can + // "pass the buck". So if there are any outlives-requirements that were + // not satisfied, we just have to report a hard error here. + if !tcx.is_closure(mir_def_id) { + for outlives_requirement in outlives_requirements { + self.report_error( + infcx, + outlives_requirement.free_region, + outlives_requirement.outlived_free_region, + outlives_requirement.blame_span, + ); + } + return None; } + + let num_external_vids = self.universal_regions.num_global_and_external_regions(); + + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements, + }) } - fn check_free_region( + /// Check the final value for the free region `fr` to see if it + /// grew too large. In particular, examine what `end(X)` points + /// wound up in `fr`'s final value; for each `end(X)` where `X != + /// fr`, we want to check that `fr: X`. If not, that's either an + /// error, or something we have to propagate to our creator. + /// + /// Things that are to be propagated are accumulated into the + /// `outlives_requirements` vector. + fn check_universal_region( &self, infcx: &InferCtxt<'_, '_, 'tcx>, longer_fr: RegionVid, - longer_definition: &RegionDefinition<'tcx>, + outlives_requirements: &mut Vec<ClosureOutlivesRequirement>, ) { let inferred_values = self.inferred_values.as_ref().unwrap(); - let longer_name = longer_definition.name.unwrap(); let longer_value = inferred_values.iter(longer_fr.index()); - // Find every region `shorter` such that `longer: shorter` - // (because `longer` includes `end(shorter)`). - for shorter_fr in longer_value.take_while(|&i| i < self.num_universal_regions) { - let shorter_fr = RegionVid::new(shorter_fr); + debug!("check_universal_region(fr={:?})", longer_fr); - // `fr` includes `end(fr)`, that's not especially - // interesting. - if longer_fr == shorter_fr { + // Find every region `o` such that `fr: o` + // (because `fr` includes `end(o)`). + let shorter_frs = longer_value + .take_while(|&i| i < self.universal_regions.len()) + .map(RegionVid::new); + for shorter_fr in shorter_frs { + // If it is known that `fr: o`, carry on. + if self.universal_regions.outlives(longer_fr, shorter_fr) { continue; } - let shorter_definition = &self.definitions[shorter_fr]; - let shorter_name = shorter_definition.name.unwrap(); - - // Check that `o <= fr`. If not, report an error. - if !self.free_region_map - .sub_free_regions(shorter_name, longer_name) - { - // FIXME: worst error msg ever - let blame_span = self.blame_span(longer_fr, shorter_fr); - infcx.tcx.sess.span_err( - blame_span, - &format!( - "free region `{}` does not outlive `{}`", - longer_name, - shorter_name - ), + debug!( + "check_universal_region: fr={:?} does not outlive shorter_fr={:?}", + longer_fr, + shorter_fr, + ); + + let blame_span = self.blame_span(longer_fr, shorter_fr); + + // Shrink `fr` until we find a non-local region (if we do). + // We'll call that `fr-` -- it's ever so slightly smaller than `fr`. + if let Some(fr_minus) = self.universal_regions.non_local_lower_bound(longer_fr) { + debug!("check_universal_region: fr_minus={:?}", fr_minus); + + // Grow `shorter_fr` until we find a non-local + // regon. (We always will.) We'll call that + // `shorter_fr+` -- it's ever so slightly larger than + // `fr`. + let shorter_fr_plus = self.universal_regions.non_local_upper_bound(shorter_fr); + debug!( + "check_universal_region: shorter_fr_plus={:?}", + shorter_fr_plus ); + + // Push the constraint `fr-: shorter_fr+` + outlives_requirements.push(ClosureOutlivesRequirement { + free_region: fr_minus, + outlived_free_region: shorter_fr_plus, + blame_span: blame_span, + }); + return; } + + // If we could not shrink `fr` to something smaller that + // the external users care about, then we can't pass the + // buck; just report an error. + self.report_error(infcx, longer_fr, shorter_fr, blame_span); } } + fn report_error( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + fr: RegionVid, + outlived_fr: RegionVid, + blame_span: Span, + ) { + // Obviously uncool error reporting. + + let fr_string = match self.definitions[fr].external_name { + Some(r) => format!("free region `{}`", r), + None => format!("free region `{:?}`", fr), + }; + + let outlived_fr_string = match self.definitions[outlived_fr].external_name { + Some(r) => format!("free region `{}`", r), + None => format!("free region `{:?}`", outlived_fr), + }; + + infcx.tcx.sess.span_err( + blame_span, + &format!("{} does not outlive {}", fr_string, outlived_fr_string,), + ); + } + /// Propagate the region constraints: this will grow the values /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be @@ -421,8 +525,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { stack.push(start_point); while let Some(p) = stack.pop() { - debug!(" copy: p={:?}", p); - if !self.region_contains_point_in_matrix(inferred_values, from_region, p) { debug!(" not in from-region"); continue; @@ -464,7 +566,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // and make sure they are included in the `to_region`. let universal_region_indices = inferred_values .iter(from_region.index()) - .take_while(|&i| i < self.num_universal_regions) + .take_while(|&i| i < self.universal_regions.len()) .collect::<Vec<_>>(); for fr in &universal_region_indices { changed |= inferred_values.add(to_region.index(), *fr); @@ -535,7 +637,11 @@ impl<'tcx> RegionDefinition<'tcx> { // Create a new region definition. Note that, for free // regions, these fields get updated later in // `init_universal_regions`. - Self { origin, name: None } + Self { + origin, + is_universal: false, + external_name: None, + } } } @@ -551,3 +657,70 @@ impl fmt::Debug for Constraint { ) } } + +pub trait ClosureRegionRequirementsExt { + fn apply_requirements<'tcx>( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + location: Location, + closure_def_id: DefId, + closure_substs: ty::ClosureSubsts<'tcx>, + ); +} + +impl ClosureRegionRequirementsExt for ClosureRegionRequirements { + /// Given an instance T of the closure type, this method + /// instantiates the "extra" requirements that we computed for the + /// closure into the inference context. This has the effect of + /// adding new subregion obligations to existing variables. + /// + /// As described on `ClosureRegionRequirements`, the extra + /// requirements are expressed in terms of regionvids that index + /// into the free regions that appear on the closure type. So, to + /// do this, we first copy those regions out from the type T into + /// a vector. Then we can just index into that vector to extract + /// out the corresponding region from T and apply the + /// requirements. + fn apply_requirements<'tcx>( + &self, + infcx: &InferCtxt<'_, '_, 'tcx>, + location: Location, + closure_def_id: DefId, + closure_substs: ty::ClosureSubsts<'tcx>, + ) { + let tcx = infcx.tcx; + + debug!( + "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})", + location, + closure_def_id, + closure_substs + ); + + // Get Tu. + let user_closure_ty = tcx.mk_closure(closure_def_id, closure_substs); + debug!("apply_requirements: user_closure_ty={:?}", user_closure_ty); + + // Extract the values of the free regions in `user_closure_ty` + // into a vector. These are the regions that we will be + // relating to one another. + let closure_mapping = + UniversalRegions::closure_mapping(infcx, user_closure_ty, self.num_external_vids); + debug!("apply_requirements: closure_mapping={:?}", closure_mapping); + + // Create the predicates. + for outlives_requirement in &self.outlives_requirements { + let region = closure_mapping[outlives_requirement.free_region]; + let outlived_region = closure_mapping[outlives_requirement.outlived_free_region]; + debug!( + "apply_requirements: region={:?} outlived_region={:?} outlives_requirements={:?}", + region, + outlived_region, + outlives_requirement + ); + // FIXME, this origin is not entirely suitable. + let origin = SubregionOrigin::CallRcvr(outlives_requirement.blame_span); + infcx.sub_regions(origin, outlived_region, region); + } + } +} diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 371419da024..1262c238a13 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::Idx; use rustc::ty::subst::Substs; -use rustc::ty::{self, ClosureSubsts, RegionVid, Ty, TypeFoldable}; +use rustc::ty::{self, ClosureSubsts, Ty, TypeFoldable}; use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind}; +use rustc::mir::RETURN_PLACE; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -25,25 +26,24 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>( universal_regions: &UniversalRegions<'tcx>, mir: &mut Mir<'tcx>, ) { - // Create inference variables for each of the free regions - // declared on the function signature. - let free_region_inference_vars = (0..universal_regions.indices.len()) - .map(RegionVid::new) - .map(|vid_expected| { - let r = infcx.next_nll_region_var(NLLRegionVariableOrigin::FreeRegion); - assert_eq!(vid_expected, r.to_region_vid()); - r - }) - .collect(); - debug!("renumber_mir()"); - debug!("renumber_mir: universal_regions={:#?}", universal_regions); debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count); + // Update the return type and types of the arguments based on the + // `universal_regions` computation. + debug!("renumber_mir: output_ty={:?}", universal_regions.output_ty); + mir.local_decls[RETURN_PLACE].ty = universal_regions.output_ty; + for (&input_ty, local) in universal_regions + .input_tys + .iter() + .zip((1..).map(Local::new)) + { + debug!("renumber_mir: input_ty={:?} local={:?}", input_ty, local); + mir.local_decls[local].ty = input_ty; + } + let mut visitor = NLLVisitor { infcx, - universal_regions, - free_region_inference_vars, arg_count: mir.arg_count, }; visitor.visit_mir(mir); @@ -51,8 +51,6 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>( struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - universal_regions: &'a UniversalRegions<'tcx>, - free_region_inference_vars: IndexVec<RegionVid, ty::Region<'tcx>>, arg_count: usize, } @@ -74,20 +72,17 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { }) } - /// Renumbers the regions appearing in `value`, but those regions - /// are expected to be free regions from the function signature. - fn renumber_universal_regions<T>(&mut self, value: &T) -> T + /// Checks that all the regions appearing in `value` have already + /// been renumbered. `FreeRegions` code should have done this. + fn assert_free_regions_are_renumbered<T>(&self, value: &T) where T: TypeFoldable<'tcx>, { - debug!("renumber_universal_regions(value={:?})", value); + debug!("assert_free_regions_are_renumbered(value={:?})", value); - self.infcx - .tcx - .fold_regions(value, &mut false, |region, _depth| { - let index = self.universal_regions.indices[®ion]; - self.free_region_inference_vars[index] - }) + self.infcx.tcx.for_each_free_region(value, |region| { + region.to_region_vid(); // will panic if `region` is not renumbered + }); } fn is_argument_or_return_slot(&self, local: Local) -> bool { @@ -110,12 +105,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { ty_context ); - let old_ty = *ty; - *ty = if is_arg { - self.renumber_universal_regions(&old_ty) + if is_arg { + self.assert_free_regions_are_renumbered(ty); } else { - self.renumber_regions(ty_context, &old_ty) - }; + *ty = self.renumber_regions(ty_context, ty); + } + debug!("visit_ty: ty={:?}", ty); } @@ -138,6 +133,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_region: region={:?}", region); } + fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Location) { + let ty_context = TyContext::Location(location); + *constant = self.renumber_regions(ty_context, &*constant); + } + fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) { debug!( "visit_closure_substs(substs={:?}, location={:?})", diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs index dbae40be6fe..c98a94fa8bc 100644 --- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs @@ -15,7 +15,6 @@ use rustc::ty; use transform::type_check::MirTypeckRegionConstraints; use transform::type_check::OutlivesSet; -use super::universal_regions::UniversalRegions; use super::region_infer::RegionInferenceContext; /// When the MIR type-checker executes, it validates all the types in @@ -25,20 +24,17 @@ use super::region_infer::RegionInferenceContext; /// them into the NLL `RegionInferenceContext`. pub(super) fn generate<'tcx>( regioncx: &mut RegionInferenceContext<'tcx>, - universal_regions: &UniversalRegions<'tcx>, mir: &Mir<'tcx>, constraints: &MirTypeckRegionConstraints<'tcx>, ) { SubtypeConstraintGenerator { regioncx, - universal_regions, mir, }.generate(constraints); } struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> { regioncx: &'cx mut RegionInferenceContext<'tcx>, - universal_regions: &'cx UniversalRegions<'tcx>, mir: &'cx Mir<'tcx>, } @@ -106,7 +102,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { if let ty::ReVar(vid) = r { *vid } else { - self.universal_regions.indices[&r] + self.regioncx.to_region_vid(r) } } } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 3be95a114c3..857a620cead 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -22,69 +22,681 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +use rustc::hir::HirId; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; -use rustc::infer::outlives::free_region_map::FreeRegionMap; -use rustc::ty::{self, RegionVid}; +use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc::infer::region_constraints::GenericKind; +use rustc::infer::outlives::bounds::{self, OutlivesBound}; +use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::transitive_relation::TransitiveRelation; +use std::iter; +use syntax::ast; + +use super::ToRegionVid; #[derive(Debug)] pub struct UniversalRegions<'tcx> { - /// Given a universally quantified region defined on this function - /// (either early- or late-bound), this maps it to its internal - /// region index. When the region context is created, the first N - /// variables will be created based on these indices. - pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>, - - /// The map from the typeck tables telling us how to relate universal regions. - pub free_region_map: &'tcx FreeRegionMap<'tcx>, + indices: UniversalRegionIndices<'tcx>, + + /// The vid assigned to `'static` + pub fr_static: RegionVid, + + /// We create region variables such that they are ordered by their + /// `RegionClassification`. The first block are globals, then + /// externals, then locals. So things from: + /// - `FIRST_GLOBAL_INDEX..first_extern_index` are global; + /// - `first_extern_index..first_local_index` are external; and + /// - first_local_index..num_universals` are local. + first_extern_index: usize, + + /// See `first_extern_index`. + first_local_index: usize, + + /// The total number of universal region variables instantiated. + num_universals: usize, + + /// The "defining" type for this function, with all universal + /// regions instantiated. For a closure or generator, this is the + /// closure type, but for a top-level function it's the `TyFnDef`. + pub defining_ty: Ty<'tcx>, + + /// The return type of this function, with all regions replaced + /// by their universal `RegionVid` equivalents. + pub output_ty: Ty<'tcx>, + + /// The fully liberated input types of this function, with all + /// regions replaced by their universal `RegionVid` equivalents. + pub input_tys: &'tcx [Ty<'tcx>], + + /// Each RBP `('a, GK)` indicates that `GK: 'a` can be assumed to + /// be true. These encode relationships like `T: 'a` that are + /// added via implicit bounds. + /// + /// Each region here is guaranteed to be a key in the `indices` + /// map. We use the "original" regions (i.e., the keys from the + /// map, and not the values) because the code in + /// `process_registered_region_obligations` has some special-cased + /// logic expecting to see (e.g.) `ReStatic`, and if we supplied + /// our special inference variable there, we would mess that up. + pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>, + + relations: UniversalRegionRelations, +} + +#[derive(Debug)] +struct UniversalRegionIndices<'tcx> { + /// For those regions that may appear in the parameter environment + /// ('static and early-bound regions), we maintain a map from the + /// `ty::Region` to the internal `RegionVid` we are using. This is + /// used because trait matching and type-checking will feed us + /// region constraints that reference those regions and we need to + /// be able to map them our internal `RegionVid`. This is + /// basically equivalent to a `Substs`, except that it also + /// contains an entry for `ReStatic` -- it might be nice to just + /// use a substs, and then handle `ReStatic` another way. + indices: FxHashMap<ty::Region<'tcx>, RegionVid>, +} + +#[derive(Debug)] +struct UniversalRegionRelations { + /// Stores the outlives relations that are known to hold from the + /// implied bounds, in-scope where clauses, and that sort of + /// thing. + outlives: TransitiveRelation<RegionVid>, + + /// This is the `<=` relation; that is, if `a: b`, then `b <= a`, + /// and we store that here. This is useful when figuring out how + /// to express some local region in terms of external regions our + /// caller will understand. + inverse_outlives: TransitiveRelation<RegionVid>, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum RegionClassification { + /// A **global** region is one that can be named from + /// anywhere. There is only one, `'static`. + Global, + + /// An **external** region is only relevant for closures. In that + /// case, it refers to regions that are free in the closure type + /// -- basically, something bound in the surrounding context. + /// + /// Consider this example: + /// + /// ``` + /// fn foo<'a, 'b>(a: &'a u32, b: &'b u32, c: &'static u32) { + /// let closure = for<'x> |x: &'x u32| { .. }; + /// ^^^^^^^ pretend this were legal syntax + /// for declaring a late-bound region in + /// a closure signature + /// } + /// ``` + /// + /// Here, the lifetimes `'a` and `'b` would be **external** to the + /// closure. + /// + /// If we are not analyzing a closure, there are no external + /// lifetimes. + External, + + /// A **local** lifetime is one about which we know the full set + /// of relevant constraints (that is, relationships to other named + /// regions). For a closure, this includes any region bound in + /// the closure's signature. For a fn item, this includes all + /// regions other than global ones. + /// + /// Continuing with the example from `External`, if we were + /// analyzing the closure, then `'x` would be local (and `'a` and + /// `'b` are external). If we are analyzing the function item + /// `foo`, then `'a` and `'b` are local (and `'x` is not in + /// scope). + Local, } -pub fn universal_regions<'a, 'gcx, 'tcx>( - infcx: &InferCtxt<'a, 'gcx, 'tcx>, - item_def_id: DefId, -) -> UniversalRegions<'tcx> { - debug!("universal_regions(item_def_id={:?})", item_def_id); +const FIRST_GLOBAL_INDEX: usize = 0; + +impl<'tcx> UniversalRegions<'tcx> { + /// Creates a new and fully initialized `UniversalRegions` that + /// contains indices for all the free regions found in the given + /// MIR -- that is, all the regions that appear in the function's + /// signature. This will also compute the relationships that are + /// known between those regions. + pub fn new( + infcx: &InferCtxt<'_, '_, 'tcx>, + mir_def_id: DefId, + param_env: ty::ParamEnv<'tcx>, + ) -> Self { + let tcx = infcx.tcx; + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).unwrap(); + let mir_hir_id = tcx.hir.node_to_hir_id(mir_node_id); + UniversalRegionsBuilder { + infcx, + mir_def_id, + mir_node_id, + mir_hir_id, + param_env, + region_bound_pairs: vec![], + relations: UniversalRegionRelations { + outlives: TransitiveRelation::new(), + inverse_outlives: TransitiveRelation::new(), + }, + }.build() + } + + /// Given a reference to a closure type, extracts all the values + /// from its free regions and returns a vector with them. This is + /// used when the closure's creator checks that the + /// `ClosureRegionRequirements` are met. The requirements from + /// `ClosureRegionRequirements` are expressed in terms of + /// `RegionVid` entries that map into the returned vector `V`: so + /// if the `ClosureRegionRequirements` contains something like + /// `'1: '2`, then the caller would impose the constraint that + /// `V[1]: V[2]`. + pub fn closure_mapping( + infcx: &InferCtxt<'_, '_, 'tcx>, + closure_ty: Ty<'tcx>, + expected_num_vars: usize, + ) -> IndexVec<RegionVid, ty::Region<'tcx>> { + let mut region_mapping = IndexVec::with_capacity(expected_num_vars); + region_mapping.push(infcx.tcx.types.re_static); + infcx.tcx.for_each_free_region(&closure_ty, |fr| { + region_mapping.push(fr); + }); + + assert_eq!( + region_mapping.len(), + expected_num_vars, + "index vec had unexpected number of variables" + ); - let mut indices = FxHashMap(); + region_mapping + } - // `'static` is always free. - insert_free_region(&mut indices, infcx.tcx.types.re_static); + /// True if `r` is a member of this set of universal regions. + pub fn is_universal_region(&self, r: RegionVid) -> bool { + (FIRST_GLOBAL_INDEX..self.num_universals).contains(r.index()) + } - // Extract the early regions. - let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id); - for item_subst in item_substs { - if let Some(region) = item_subst.as_region() { - insert_free_region(&mut indices, region); + /// Classifies `r` as a universal region, returning `None` if this + /// is not a member of this set of universal regions. + pub fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> { + let index = r.index(); + if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(index) { + Some(RegionClassification::Global) + } else if (self.first_extern_index..self.first_local_index).contains(index) { + Some(RegionClassification::External) + } else if (self.first_local_index..self.num_universals).contains(index) { + Some(RegionClassification::Local) + } else { + None } } - // Extract the late-bound regions. Use the liberated fn sigs, - // where the late-bound regions will have been converted into free - // regions, and add them to the map. - let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap(); - let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id); - let tables = infcx.tcx.typeck_tables_of(item_def_id); - let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone(); - infcx - .tcx - .for_each_free_region(&fn_sig.inputs_and_output, |region| { - if let ty::ReFree(_) = *region { - insert_free_region(&mut indices, region); + /// Returns an iterator over all the RegionVids corresponding to + /// universally quantified free regions. + pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> { + (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new) + } + + /// True if `r` is classied as a global region. + pub fn is_global_free_region(&self, r: RegionVid) -> bool { + self.region_classification(r) == Some(RegionClassification::Global) + } + + /// True if `r` is classied as an external region. + pub fn is_extern_free_region(&self, r: RegionVid) -> bool { + self.region_classification(r) == Some(RegionClassification::External) + } + + /// True if `r` is classied as an local region. + pub fn is_local_free_region(&self, r: RegionVid) -> bool { + self.region_classification(r) == Some(RegionClassification::Local) + } + + /// Returns the number of universal regions created in any category. + pub fn len(&self) -> usize { + self.num_universals + } + + /// Finds an "upper bound" for `fr` that is not local. In other + /// words, returns the smallest (*) known region `fr1` that (a) + /// outlives `fr` and (b) is not local. This cannot fail, because + /// we will always find `'static` at worst. + /// + /// (*) If there are multiple competing choices, we pick the "postdominating" + /// one. See `TransitiveRelation::postdom_upper_bound` for details. + pub fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid { + debug!("non_local_upper_bound(fr={:?})", fr); + self.non_local_bound(&self.relations.inverse_outlives, fr) + .unwrap_or(self.fr_static) + } + + /// Finds a "lower bound" for `fr` that is not local. In other + /// words, returns the largest (*) known region `fr1` that (a) is + /// outlived by `fr` and (b) is not local. This cannot fail, + /// because we will always find `'static` at worst. + /// + /// (*) If there are multiple competing choices, we pick the "postdominating" + /// one. See `TransitiveRelation::postdom_upper_bound` for details. + pub fn non_local_lower_bound(&self, fr: RegionVid) -> Option<RegionVid> { + debug!("non_local_lower_bound(fr={:?})", fr); + self.non_local_bound(&self.relations.outlives, fr) + } + + /// Returns the number of global plus external universal regions. + /// For closures, these are the regions that appear free in the + /// closure type (versus those bound in the closure + /// signature). They are therefore the regions between which the + /// closure may impose constraints that its creator must verify. + pub fn num_global_and_external_regions(&self) -> usize { + self.first_local_index + } + + /// Helper for `non_local_upper_bound` and + /// `non_local_lower_bound`. Repeatedly invokes `postdom_parent` + /// until we find something that is not local. Returns None if we + /// never do so. + fn non_local_bound( + &self, + relation: &TransitiveRelation<RegionVid>, + fr0: RegionVid, + ) -> Option<RegionVid> { + let mut external_parents = vec![]; + let mut queue = vec![&fr0]; + + // Keep expanding `fr` into its parents until we reach + // non-local regions. + while let Some(fr) = queue.pop() { + if !self.is_local_free_region(*fr) { + external_parents.push(fr); + continue; } - }); - debug!("universal_regions: indices={:#?}", indices); + queue.extend(relation.parents(fr)); + } + + debug!("non_local_bound: external_parents={:?}", external_parents); + + // In case we find more than one, reduce to one for + // convenience. This is to prevent us from generating more + // complex constraints, but it will cause spurious errors. + let post_dom = relation + .mutual_immediate_postdominator(external_parents) + .cloned(); + + debug!("non_local_bound: post_dom={:?}", post_dom); + + post_dom.and_then(|post_dom| { + // If the mutual immediate postdom is not local, then + // there is no non-local result we can return. + if !self.is_local_free_region(post_dom) { + Some(post_dom) + } else { + None + } + }) + } + + /// True if fr1 is known to outlive fr2. + /// + /// This will only ever be true for universally quantified regions. + pub fn outlives(&self, fr1: RegionVid, fr2: RegionVid) -> bool { + self.relations.outlives.contains(&fr1, &fr2) + } + + /// Returns a vector of free regions `x` such that `fr1: x` is + /// known to hold. + pub fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<&RegionVid> { + self.relations.outlives.reachable_from(&fr1) + } + + /// Get an iterator over all the early-bound regions that have names. + pub fn named_universal_regions<'s>( + &'s self, + ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's { + self.indices.indices.iter().map(|(&r, &v)| (r, v)) + } + + /// See `UniversalRegionIndices::to_region_vid`. + pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + self.indices.to_region_vid(r) + } +} + +struct UniversalRegionsBuilder<'cx, 'gcx: 'tcx, 'tcx: 'cx> { + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, + mir_def_id: DefId, + mir_hir_id: HirId, + mir_node_id: ast::NodeId, + param_env: ty::ParamEnv<'tcx>, + region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>, + relations: UniversalRegionRelations, +} + +const FR: NLLRegionVariableOrigin = NLLRegionVariableOrigin::FreeRegion; + +impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { + fn build(mut self) -> UniversalRegions<'tcx> { + debug!("build(mir_def_id={:?})", self.mir_def_id); + + let param_env = self.param_env; + debug!("build: param_env={:?}", param_env); + + assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars()); + + // Create the "global" region that is always free in all contexts: 'static. + let fr_static = self.infcx.next_nll_region_var(FR).to_region_vid(); + + // We've now added all the global regions. The next ones we + // add will be external. + let first_extern_index = self.infcx.num_region_vars(); + + let defining_ty = self.defining_ty(); + debug!("build: defining_ty={:?}", defining_ty); + + let indices = self.compute_indices(fr_static, defining_ty); + debug!("build: indices={:?}", indices); + + let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty); + + // "Liberate" the late-bound regions. These correspond to + // "local" free regions. + let first_local_index = self.infcx.num_region_vars(); + let inputs_and_output = self.infcx + .replace_bound_regions_with_nll_infer_vars(FR, &bound_inputs_and_output); + let num_universals = self.infcx.num_region_vars(); + + // Insert the facts we know from the predicates. Why? Why not. + self.add_outlives_bounds(&indices, bounds::explicit_outlives_bounds(param_env)); + + // Add the implied bounds from inputs and outputs. + for ty in inputs_and_output { + debug!("build: input_or_output={:?}", ty); + self.add_implied_bounds(&indices, ty); + } + + // Finally, outlives is reflexive, and static outlives every + // other free region. + for fr in (FIRST_GLOBAL_INDEX..num_universals).map(RegionVid::new) { + debug!("build: relating free region {:?} to itself and to 'static", fr); + self.relations.relate_universal_regions(fr, fr); + self.relations.relate_universal_regions(fr_static, fr); + } + + let (output_ty, input_tys) = inputs_and_output.split_last().unwrap(); + + // we should not have created any more variables + assert_eq!(self.infcx.num_region_vars(), num_universals); + + debug!("build: global regions = {}..{}", + FIRST_GLOBAL_INDEX, + first_extern_index); + debug!("build: extern regions = {}..{}", + first_extern_index, + first_local_index); + debug!("build: local regions = {}..{}", + first_local_index, + num_universals); + + UniversalRegions { + indices, + fr_static, + first_extern_index, + first_local_index, + num_universals, + defining_ty, + output_ty, + input_tys, + region_bound_pairs: self.region_bound_pairs, + relations: self.relations, + } + } + + fn defining_ty(&self) -> ty::Ty<'tcx> { + let tcx = self.infcx.tcx; + let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); + + let defining_ty = if self.mir_def_id == closure_base_def_id { + tcx.type_of(closure_base_def_id) + } else { + let tables = tcx.typeck_tables_of(self.mir_def_id); + tables.node_id_to_type(self.mir_hir_id) + }; + + self.infcx + .replace_free_regions_with_nll_infer_vars(FR, &defining_ty) + } + + fn compute_indices( + &self, + fr_static: RegionVid, + defining_ty: Ty<'tcx>, + ) -> UniversalRegionIndices<'tcx> { + let tcx = self.infcx.tcx; + let gcx = tcx.global_tcx(); + let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); + let identity_substs = Substs::identity_for_item(gcx, closure_base_def_id); + let fr_substs = match defining_ty.sty { + ty::TyClosure(_, substs) | ty::TyGenerator(_, substs, ..) => { + // In the case of closures, we rely on the fact that + // the first N elements in the ClosureSubsts are + // inherited from the `closure_base_def_id`. + // Therefore, when we zip together (below) with + // `identity_substs`, we will get only those regions + // that correspond to early-bound regions declared on + // the `closure_base_def_id`. + assert!(substs.substs.len() >= identity_substs.len()); + substs.substs + } + ty::TyFnDef(_, substs) => substs, + _ => bug!(), + }; + + let global_mapping = iter::once((gcx.types.re_static, fr_static)); + let subst_mapping = identity_substs + .regions() + .zip(fr_substs.regions().map(|r| r.to_region_vid())); + + UniversalRegionIndices { + indices: global_mapping.chain(subst_mapping).collect(), + } + } + + fn compute_inputs_and_output( + &self, + indices: &UniversalRegionIndices<'tcx>, + defining_ty: Ty<'tcx>, + ) -> ty::Binder<&'tcx ty::Slice<Ty<'tcx>>> { + let tcx = self.infcx.tcx; + match defining_ty.sty { + ty::TyClosure(def_id, substs) => { + assert_eq!(self.mir_def_id, def_id); + let closure_sig = substs.closure_sig_ty(def_id, tcx).fn_sig(tcx); + let inputs_and_output = closure_sig.inputs_and_output(); + let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + ty::Binder::fuse( + closure_ty, + inputs_and_output, + |closure_ty, inputs_and_output| { + // The "inputs" of the closure in the + // signature appear as a tuple. The MIR side + // flattens this tuple. + let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); + assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); + let inputs = match tuplized_inputs[0].sty { + ty::TyTuple(inputs, _) => inputs, + _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), + }; - UniversalRegions { indices, free_region_map: &tables.free_region_map } + tcx.mk_type_list( + iter::once(closure_ty) + .chain(inputs.iter().cloned()) + .chain(iter::once(output)), + ) + }, + ) + } + + ty::TyGenerator(def_id, substs, ..) => { + assert_eq!(self.mir_def_id, def_id); + let output = substs.generator_return_ty(def_id, tcx); + let inputs_and_output = self.infcx.tcx.intern_type_list(&[defining_ty, output]); + ty::Binder::dummy(inputs_and_output) + } + + ty::TyFnDef(def_id, _) => { + let sig = tcx.fn_sig(def_id); + let sig = indices.fold_to_region_vids(tcx, &sig); + return sig.inputs_and_output(); + } + + _ => span_bug!( + tcx.def_span(self.mir_def_id), + "unexpected defining type: {:?}", + defining_ty + ), + } + } + + /// Update the type of a single local, which should represent + /// either the return type of the MIR or one of its arguments. At + /// the same time, compute and add any implied bounds that come + /// from this local. + /// + /// Assumes that `universal_regions` indices map is fully constructed. + fn add_implied_bounds(&mut self, indices: &UniversalRegionIndices<'tcx>, ty: Ty<'tcx>) { + debug!("add_implied_bounds(ty={:?})", ty); + let span = self.infcx.tcx.def_span(self.mir_def_id); + let bounds = self.infcx + .implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span); + self.add_outlives_bounds(indices, bounds); + } + + /// Registers the `OutlivesBound` items from `outlives_bounds` in + /// the outlives relation as well as the region-bound pairs + /// listing. + fn add_outlives_bounds<I>(&mut self, indices: &UniversalRegionIndices<'tcx>, outlives_bounds: I) + where + I: IntoIterator<Item = OutlivesBound<'tcx>>, + { + for outlives_bound in outlives_bounds { + debug!("add_outlives_bounds(bound={:?})", outlives_bound); + + match outlives_bound { + OutlivesBound::RegionSubRegion(r1, r2) => { + // The bound says that `r1 <= r2`; we store `r2: r1`. + let r1 = indices.to_region_vid(r1); + let r2 = indices.to_region_vid(r2); + self.relations.relate_universal_regions(r2, r1); + } + + OutlivesBound::RegionSubParam(r_a, param_b) => { + self.region_bound_pairs + .push((r_a, GenericKind::Param(param_b))); + } + + OutlivesBound::RegionSubProjection(r_a, projection_b) => { + self.region_bound_pairs + .push((r_a, GenericKind::Projection(projection_b))); + } + } + } + } +} + +impl UniversalRegionRelations { + /// Records in the `outlives_relation` (and + /// `inverse_outlives_relation`) that `fr_a: fr_b`. + fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) { + debug!( + "relate_universal_regions: fr_a={:?} outlives fr_b={:?}", + fr_a, + fr_b + ); + self.outlives.add(fr_a, fr_b); + self.inverse_outlives.add(fr_b, fr_a); + } +} + +pub(crate) trait InferCtxtExt<'tcx> { + fn replace_free_regions_with_nll_infer_vars<T>( + &self, + origin: NLLRegionVariableOrigin, + value: &T, + ) -> T + where + T: TypeFoldable<'tcx>; + + fn replace_bound_regions_with_nll_infer_vars<T>( + &self, + origin: NLLRegionVariableOrigin, + value: &ty::Binder<T>, + ) -> T + where + T: TypeFoldable<'tcx>; +} + +impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { + fn replace_free_regions_with_nll_infer_vars<T>( + &self, + origin: NLLRegionVariableOrigin, + value: &T, + ) -> T + where + T: TypeFoldable<'tcx>, + { + self.tcx.fold_regions( + value, + &mut false, + |_region, _depth| self.next_nll_region_var(origin), + ) + } + + fn replace_bound_regions_with_nll_infer_vars<T>( + &self, + origin: NLLRegionVariableOrigin, + value: &ty::Binder<T>, + ) -> T + where + T: TypeFoldable<'tcx>, + { + let (value, _map) = self.tcx + .replace_late_bound_regions(value, |_br| self.next_nll_region_var(origin)); + value + } } -fn insert_free_region<'tcx>( - universal_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>, - region: ty::Region<'tcx>, -) { - let next = RegionVid::new(universal_regions.len()); - universal_regions.entry(region).or_insert(next); +impl<'tcx> UniversalRegionIndices<'tcx> { + /// Converts `r` into a local inference variable: `r` can either + /// by a `ReVar` (i.e., already a reference to an inference + /// variable) or it can be `'static` or some early-bound + /// region. This is useful when taking the results from + /// type-checking and trait-matching, which may sometimes + /// reference those regions from the `ParamEnv`. It is also used + /// during initialization. Relies on the `indices` map having been + /// fully initialized. + pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + match r { + ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(), + ty::ReVar(..) => r.to_region_vid(), + _ => bug!("cannot convert `{:?}` to a region vid", r), + } + } + + /// Replace all free regions in `value` with region vids, as + /// returned by `to_region_vid`. + pub fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'_, '_, 'tcx>, value: &T) -> T + where + T: TypeFoldable<'tcx>, + { + tcx.fold_regions( + value, + &mut false, + |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))), + ) + } } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index d1bb1f39e22..932aad0bb1d 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -51,6 +51,17 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, region_scope: region::Scope) { if tcx.sess.emit_end_regions() { + if let region::ScopeData::CallSite(_) = region_scope.data() { + // The CallSite scope (aka the root scope) is sort of weird, in that it is + // supposed to "separate" the "interior" and "exterior" of a closure. Being + // that, it is not really a part of the region hierarchy, but for some + // reason it *is* considered a part of it. + // + // It should die a hopefully painful death with NLL, so let's leave this hack + // for now so that nobody can complain about soundness. + return + } + self.push(block, Statement { source_info, kind: StatementKind::EndRegion(region_scope), diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 2bba3e263f3..c27cb43eff7 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir; +use rustc::hir::def_id::DefId; +use rustc::middle::region; use rustc::mir::{self, Location, Mir}; use rustc::mir::visit::Visitor; use rustc::ty::{self, Region, TyCtxt}; @@ -27,6 +30,7 @@ use borrow_check::nll::ToRegionVid; use syntax_pos::Span; use std::fmt; +use std::rc::Rc; // `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be // uniquely identified in the MIR by the `Location` of the assigment @@ -34,9 +38,12 @@ use std::fmt; pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, + scope_tree: Rc<region::ScopeTree>, + root_scope: Option<region::Scope>, borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>, location_map: FxHashMap<Location, BorrowIndex>, region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>, + local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>, region_span_map: FxHashMap<RegionKind, Span>, nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>, } @@ -69,22 +76,32 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, - nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>) + nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>, + def_id: DefId, + body_id: Option<hir::BodyId>) -> Self { + let scope_tree = tcx.region_scope_tree(def_id); + let root_scope = body_id.map(|body_id| { + region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) + }); let mut visitor = GatherBorrows { tcx, mir, idx_vec: IndexVec::new(), location_map: FxHashMap(), region_map: FxHashMap(), + local_map: FxHashMap(), region_span_map: FxHashMap() }; visitor.visit_mir(mir); return Borrows { tcx: tcx, mir: mir, borrows: visitor.idx_vec, + scope_tree, + root_scope, location_map: visitor.location_map, region_map: visitor.region_map, + local_map: visitor.local_map, region_span_map: visitor.region_span_map, nonlexical_regioncx }; @@ -94,6 +111,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>, location_map: FxHashMap<Location, BorrowIndex>, region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>, + local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>, region_span_map: FxHashMap<RegionKind, Span>, } @@ -101,6 +119,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) { + fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> { + loop { match p { + mir::Place::Projection(pi) => p = &pi.base, + mir::Place::Static(_) => return None, + mir::Place::Local(l) => return Some(*l) + }} + } + if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue { if is_unsafe_place(self.tcx, self.mir, place) { return; } @@ -109,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { }; let idx = self.idx_vec.push(borrow); self.location_map.insert(location, idx); + let borrows = self.region_map.entry(region).or_insert(FxHashSet()); borrows.insert(idx); + + if let Some(local) = root_local(place) { + let borrows = self.local_map.entry(local).or_insert(FxHashSet()); + borrows.insert(idx); + } } } @@ -199,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::EndRegion(region_scope) => { if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) { assert!(self.nonlexical_regioncx.is_none()); - for idx in borrow_indexes { sets.kill(&idx); } + sets.kill_all(borrow_indexes); } else { // (if there is no entry, then there are no borrows to be tracked) } @@ -224,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } } + mir::StatementKind::StorageDead(local) => { + // Make sure there are no remaining borrows for locals that + // are gone out of scope. + // + // FIXME: expand this to variables that are assigned over. + if let Some(borrow_indexes) = self.local_map.get(&local) { + sets.kill_all(borrow_indexes); + } + } + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | - mir::StatementKind::StorageDead(..) | mir::StatementKind::Validate(..) | mir::StatementKind::Nop => {} @@ -253,8 +294,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // like unwind paths, we do not always emit `EndRegion` statements, so we // add some kills here as a "backup" and to avoid spurious error messages. for (borrow_index, borrow_data) in self.borrows.iter_enumerated() { - if let ReScope(..) = borrow_data.region { - sets.kill(&borrow_index); + if let ReScope(scope) = borrow_data.region { + // Check that the scope is not actually a scope from a function that is + // a parent of our closure. Note that the CallSite scope itself is + // *outside* of the closure, for some weird reason. + if let Some(root_scope) = self.root_scope { + if *scope != root_scope && + self.scope_tree.is_subscope_of(*scope, root_scope) + { + sets.kill(&borrow_index); + } + } } } } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 50c8df3c2e3..db8ca0628c4 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,6 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; @@ -504,7 +503,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { let stmt = &mir[location.block].statements[location.statement_index]; let loc_map = &move_data.loc_map; let path_map = &move_data.path_map; - let bits_per_block = self.bits_per_block(); match stmt.kind { // this analysis only tries to find moves explicitly @@ -515,21 +513,15 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { _ => { debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", stmt, location, &loc_map[location]); - for move_index in &loc_map[location] { - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - zero_to_one(sets.gen_set.words_mut(), *move_index); - } + // Every path deinitialized by a *particular move* + // has corresponding bit, "gen'ed" (i.e. set) + // here, in dataflow vector + sets.gen_all_and_assert_dead(&loc_map[location]); } } for_location_inits(tcx, mir, move_data, location, - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - } - ); + |mpi| sets.kill_all(&path_map[mpi])); } fn terminator_effect(&self, @@ -543,18 +535,10 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", term, location, &loc_map[location]); - let bits_per_block = self.bits_per_block(); - for move_index in &loc_map[location] { - assert!(move_index.index() < bits_per_block); - zero_to_one(sets.gen_set.words_mut(), *move_index); - } + sets.gen_all_and_assert_dead(&loc_map[location]); for_location_inits(tcx, mir, move_data, location, - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - } - ); + |mpi| sets.kill_all(&path_map[mpi])); } fn propagate_call_return(&self, @@ -585,11 +569,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { } fn start_block_effect(&self, sets: &mut BlockSets<InitIndex>) { - let bits_per_block = self.bits_per_block(); - for init_index in (0..self.mir.arg_count).map(InitIndex::new) { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(&init_index); - } + sets.gen_all((0..self.mir.arg_count).map(InitIndex::new)); } fn statement_effect(&self, sets: &mut BlockSets<InitIndex>, @@ -599,26 +579,39 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { let init_path_map = &move_data.init_path_map; let init_loc_map = &move_data.init_loc_map; let rev_lookup = &move_data.rev_lookup; - let bits_per_block = self.bits_per_block(); debug!("statement {:?} at loc {:?} initializes move_indexes {:?}", stmt, location, &init_loc_map[location]); - for init_index in &init_loc_map[location] { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(init_index); - } + sets.gen_all(&init_loc_map[location]); match stmt.kind { - mir::StatementKind::StorageDead(local) => { - // End inits for StorageDead, so that an immutable variable can - // be reinitialized on the next iteration of the loop. + mir::StatementKind::StorageDead(local) | + mir::StatementKind::StorageLive(local) => { + // End inits for StorageDead and StorageLive, so that an immutable + // variable can be reinitialized on the next iteration of the loop. + // + // FIXME(#46525): We *need* to do this for StorageLive as well as + // StorageDead, because lifetimes of match bindings with guards are + // weird - i.e. this code + // + // ``` + // fn main() { + // match 0 { + // a | a + // if { println!("a={}", a); false } => {} + // _ => {} + // } + // } + // ``` + // + // runs the guard twice, using the same binding for `a`, and only + // storagedeads after everything ends, so if we don't regard the + // storagelive as killing storage, we would have a multiple assignment + // to immutable data error. if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) { debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}", - stmt, location, &init_path_map[mpi]); - for ii in &init_path_map[mpi] { - assert!(ii.index() < bits_per_block); - sets.kill_set.add(&ii); - } + stmt, location, &init_path_map[mpi]); + sets.kill_all(&init_path_map[mpi]); } } _ => {} @@ -634,13 +627,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { let init_loc_map = &move_data.init_loc_map; debug!("terminator {:?} at loc {:?} initializes move_indexes {:?}", term, location, &init_loc_map[location]); - let bits_per_block = self.bits_per_block(); - for init_index in &init_loc_map[location] { - if move_data.inits[*init_index].kind != InitKind::NonPanicPathOnly { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(init_index); - } - } + sets.gen_all( + init_loc_map[location].iter().filter(|init_index| { + move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly + }) + ); } fn propagate_call_return(&self, @@ -663,11 +654,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { } } -fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) { - let retval = bitvec.set_bit(move_index.index()); - assert!(retval); -} - impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 6be006b1ea9..12722979706 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -18,6 +18,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::session::Session; +use std::borrow::Borrow; use std::fmt::{self, Debug}; use std::io; use std::mem; @@ -492,10 +493,39 @@ impl<'a, E:Idx> BlockSets<'a, E> { self.gen_set.add(e); self.kill_set.remove(e); } + fn gen_all<I>(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow<E> + { + for j in i { + self.gen(j.borrow()); + } + } + + fn gen_all_and_assert_dead<I>(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow<E> + { + for j in i { + let j = j.borrow(); + let retval = self.gen_set.add(j); + self.kill_set.remove(j); + assert!(retval); + } + } + fn kill(&mut self, e: &E) { self.gen_set.remove(e); self.kill_set.add(e); } + fn kill_all<I>(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow<E> + { + for j in i { + self.kill(j.borrow()); + } + } } impl<E:Idx> AllSets<E> { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b9b86dd6e84..2b2323928ef 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -41,6 +41,9 @@ use transform::{MirPass, MirSource}; use super::promote_consts::{self, Candidate, TempState}; bitflags! { + // Borrows of temporaries can be promoted only if + // they have none of these qualifications, with + // the exception of `STATIC_REF` (in statics only). struct Qualif: u8 { // Constant containing interior mutability (UnsafeCell). const MUTABLE_INTERIOR = 1 << 0; @@ -65,10 +68,6 @@ bitflags! { // promote_consts decided they weren't simple enough. const NOT_PROMOTABLE = 1 << 6; - // Borrows of temporaries can be promoted only - // if they have none of the above qualifications. - const NEVER_PROMOTE = 0b111_1111; - // Const items can only have MUTABLE_INTERIOR // and NOT_PROMOTABLE without producing an error. const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits & @@ -197,7 +196,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { self.add(original); } - /// Check if an Place with the current qualifications could + /// Check if a Local with the current qualifications is promotable. + fn can_promote(&mut self) -> bool { + // References to statics are allowed, but only in other statics. + if self.mode == Mode::Static || self.mode == Mode::StaticMut { + (self.qualif - Qualif::STATIC_REF).is_empty() + } else { + self.qualif.is_empty() + } + } + + /// Check if a Place with the current qualifications could /// be consumed, by either an operand or a Deref projection. fn try_consume(&mut self) -> bool { if self.qualif.intersects(Qualif::STATIC) && self.mode != Mode::Fn { @@ -633,7 +642,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // We might have a candidate for promotion. let candidate = Candidate::Ref(location); - if !self.qualif.intersects(Qualif::NEVER_PROMOTE) { + if self.can_promote() { // We can only promote direct borrows of temps. if let Place::Local(local) = *place { if self.mir.local_kind(local) == LocalKind::Temp { @@ -745,7 +754,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { this.visit_operand(arg, location); if is_shuffle && i == 2 && this.mode == Mode::Fn { let candidate = Candidate::ShuffleIndices(bb); - if !this.qualif.intersects(Qualif::NEVER_PROMOTE) { + if this.can_promote() { this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index f0b62e28a0d..1a74f327001 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -11,6 +11,7 @@ //! This pass type-checks the MIR to ensure it is not broken. #![allow(unreachable_code)] +use borrow_check::nll::region_infer::ClosureRegionRequirementsExt; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::infer::region_constraints::RegionConstraintData; use rustc::traits::{self, FulfillmentContext}; @@ -110,6 +111,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); + self.sanitize_constant(constant, location); self.sanitize_type(constant, constant.ty); } @@ -159,6 +161,52 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } + /// Checks that the constant's `ty` field matches up with what + /// would be expected from its literal. + fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + debug!( + "sanitize_constant(constant={:?}, location={:?})", + constant, + location + ); + + let expected_ty = match constant.literal { + Literal::Value { value } => value.ty, + Literal::Promoted { .. } => { + // FIXME -- promoted MIR return types reference + // various "free regions" (e.g., scopes and things) + // that they ought not to do. We have to figure out + // how best to handle that -- probably we want treat + // promoted MIR much like closures, renumbering all + // their free regions and propagating constraints + // upwards. We have the same acyclic guarantees, so + // that should be possible. But for now, ignore them. + // + // let promoted_mir = &self.mir.promoted[index]; + // promoted_mir.return_ty() + return; + } + }; + + debug!("sanitize_constant: expected_ty={:?}", expected_ty); + + if let Err(terr) = self.cx + .eq_types(expected_ty, constant.ty, location.at_self()) + { + span_mirbug!( + self, + constant, + "constant {:?} should have type {:?} but has {:?} ({:?})", + constant, + expected_ty, + constant.ty, + terr, + ); + } + } + + /// Checks that the types internal to the `place` match up with + /// what would be expected. fn sanitize_place( &mut self, place: &Place<'tcx>, @@ -1088,14 +1136,45 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { operands: &[Operand<'tcx>], location: Location, ) { + let tcx = self.tcx(); + match aggregate_kind { // tuple rvalue field type is always the type of the op. Nothing to check here. AggregateKind::Tuple => return, + + // For closures, we have some **extra requirements** we + // have to check. In particular, in their upvars and + // signatures, closures often reference various regions + // from the surrounding function -- we call those the + // closure's free regions. When we borrow-check (and hence + // region-check) closures, we may find that the closure + // requires certain relationships between those free + // regions. However, because those free regions refer to + // portions of the CFG of their caller, the closure is not + // in a position to verify those relationships. In that + // case, the requirements get "propagated" to us, and so + // we have to solve them here where we instantiate the + // closure. + // + // Despite the opacity of the previous parapgrah, this is + // actually relatively easy to understand in terms of the + // desugaring. A closure gets desugared to a struct, and + // these extra requirements are basically like where + // clauses on the struct. + AggregateKind::Closure(def_id, substs) => { + if let Some(closure_region_requirements) = tcx.mir_borrowck(*def_id) { + closure_region_requirements.apply_requirements( + self.infcx, + location, + *def_id, + *substs, + ); + } + } + _ => {} } - let tcx = self.tcx(); - for (i, operand) in operands.iter().enumerate() { let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) { Ok(field_ty) => field_ty, diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 8a3db0eb25b..37f59773cd6 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -11,7 +11,8 @@ use rustc::hir; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::*; -use rustc::ty::TyCtxt; +use rustc::mir::visit::Visitor; +use rustc::ty::{self, TyCtxt}; use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -56,9 +57,19 @@ pub enum PassWhere { /// where `<filter>` takes the following forms: /// /// - `all` -- dump MIR for all fns, all passes, all everything -/// - `substring1&substring2,...` -- `&`-separated list of substrings -/// that can appear in the pass-name or the `item_path_str` for the given -/// node-id. If any one of the substrings match, the data is dumped out. +/// - a filter defined by a set of substrings combined with `&` and `|` +/// (`&` has higher precedence). At least one of the `|`-separated groups +/// must match; an `|`-separated group matches if all of its `&`-separated +/// substrings are matched. +/// +/// Example: +/// +/// - `nll` == match if `nll` appears in the name +/// - `foo & nll` == match if `foo` and `nll` both appear in the name +/// - `foo & nll | typeck` == match if `foo` and `nll` both appear in the name +/// or `typeck` appears in the name. +/// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name +/// or `typeck` and `bar` both appear in the name. pub fn dump_mir<'a, 'gcx, 'tcx, F>( tcx: TyCtxt<'a, 'gcx, 'tcx>, pass_num: Option<&Display>, @@ -103,8 +114,10 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( // see notes on #41697 below tcx.item_path_str(source.def_id) }); - filters.split("&").any(|filter| { - filter == "all" || pass_name.contains(filter) || node_path.contains(filter) + filters.split("|").any(|or_filter| { + or_filter.split("&").all(|and_filter| { + and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter) + }) }) } @@ -125,14 +138,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( F: FnMut(PassWhere, &mut Write) -> io::Result<()>, { let _: io::Result<()> = do catch { - let mut file = create_dump_file( - tcx, - "mir", - pass_num, - pass_name, - disambiguator, - source, - )?; + let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; writeln!(file, "// MIR for `{}`", node_path)?; writeln!(file, "// source = {:?}", source)?; writeln!(file, "// pass_name = {}", pass_name)?; @@ -148,15 +154,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( }; if tcx.sess.opts.debugging_opts.dump_mir_graphviz { - let _: io::Result<()> = do catch { - let mut file = create_dump_file( - tcx, - "dot", - pass_num, - pass_name, - disambiguator, - source, - )?; + let _: io::Result<()> = do catch { + let mut file = + create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?; write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?; Ok(()) }; @@ -297,10 +297,10 @@ where } /// Write out a human-readable textual representation for the given basic block. -pub fn write_basic_block<F>( - tcx: TyCtxt, +pub fn write_basic_block<'cx, 'gcx, 'tcx, F>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, block: BasicBlock, - mir: &Mir, + mir: &Mir<'tcx>, extra_data: &mut F, w: &mut Write, ) -> io::Result<()> @@ -330,6 +330,11 @@ where comment(tcx, statement.source_info), A = ALIGN, )?; + + write_extra(tcx, w, |visitor| { + visitor.visit_statement(current_location.block, statement, current_location); + })?; + extra_data(PassWhere::AfterLocation(current_location), w)?; current_location.statement_index += 1; @@ -346,11 +351,94 @@ where comment(tcx, data.terminator().source_info), A = ALIGN, )?; + + write_extra(tcx, w, |visitor| { + visitor.visit_terminator(current_location.block, data.terminator(), current_location); + })?; + extra_data(PassWhere::AfterLocation(current_location), w)?; writeln!(w, "{}}}", INDENT) } +/// After we print the main statement, we sometimes dump extra +/// information. There's often a lot of little things "nuzzled up" in +/// a statement. +fn write_extra<'cx, 'gcx, 'tcx, F>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + write: &mut Write, + mut visit_op: F, +) -> io::Result<()> +where + F: FnMut(&mut ExtraComments<'cx, 'gcx, 'tcx>), +{ + let mut extra_comments = ExtraComments { + _tcx: tcx, + comments: vec![], + }; + visit_op(&mut extra_comments); + for comment in extra_comments.comments { + writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?; + } + Ok(()) +} + +struct ExtraComments<'cx, 'gcx: 'tcx, 'tcx: 'cx> { + _tcx: TyCtxt<'cx, 'gcx, 'tcx>, // don't need it now, but bet we will soon + comments: Vec<String>, +} + +impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> { + fn push(&mut self, lines: &str) { + for line in lines.split("\n") { + self.comments.push(line.to_string()); + } + } +} + +impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> { + fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + self.super_constant(constant, location); + let Constant { span, ty, literal } = constant; + self.push(&format!("mir::Constant")); + self.push(&format!("└ span: {:?}", span)); + self.push(&format!("└ ty: {:?}", ty)); + self.push(&format!("└ literal: {:?}", literal)); + } + + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { + self.super_const(constant); + let ty::Const { ty, val } = constant; + self.push(&format!("ty::Const")); + self.push(&format!("└ ty: {:?}", ty)); + self.push(&format!("└ val: {:?}", val)); + } + + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { + self.super_rvalue(rvalue, location); + match rvalue { + Rvalue::Aggregate(kind, _) => match **kind { + AggregateKind::Closure(def_id, substs) => { + self.push(&format!("closure")); + self.push(&format!("└ def_id: {:?}", def_id)); + self.push(&format!("└ substs: {:#?}", substs)); + } + + AggregateKind::Generator(def_id, substs, interior) => { + self.push(&format!("generator")); + self.push(&format!("└ def_id: {:?}", def_id)); + self.push(&format!("└ substs: {:#?}", substs)); + self.push(&format!("└ interior: {:?}", interior)); + } + + _ => {} + }, + + _ => {} + } + } +} + fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String { format!( "scope {} at {}", diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 97cea5c9d64..05ad1643619 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,6 +21,7 @@ use rustc::session::Session; use syntax::ast::*; use syntax::attr; use syntax::codemap::Spanned; +use syntax::parse::token; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -35,8 +36,16 @@ impl<'a> AstValidator<'a> { &self.session.parse_sess.span_diagnostic } + fn check_lifetime(&self, lifetime: &Lifetime) { + let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()]; + if !valid_names.contains(&lifetime.ident.name) && + token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() { + self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names"); + } + } + fn check_label(&self, label: Ident, span: Span) { - if label.name == keywords::StaticLifetime.name() || label.name == "'_" { + if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" { self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name)); } } @@ -200,6 +209,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_use_tree(self, use_tree, id); } + fn visit_lifetime(&mut self, lifetime: &'a Lifetime) { + self.check_lifetime(lifetime); + visit::walk_lifetime(self, lifetime); + } + fn visit_item(&mut self, item: &'a Item) { match item.node { ItemKind::Impl(.., Some(..), _, ref impl_items) => { diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 405647af324..762cf7a0055 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -29,7 +29,7 @@ use value::Value; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; -use rustc::ty::subst::{Kind, Subst, Substs}; +use rustc::ty::subst::{Kind, Substs}; use rustc::hir; use libc::{c_uint, c_char}; @@ -393,7 +393,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()), ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs); + let sig = substs.closure_sig(def_id, tcx); let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); sig.map_bound(|sig| tcx.mk_fn_sig( diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index cfca3b57cb9..800c7733c3d 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -74,7 +74,7 @@ pub fn addr_of_mut(ccx: &CrateContext, }); llvm::LLVMSetInitializer(gv, cv); set_global_alignment(ccx, gv, align); - llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage); + llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); SetUnnamedAddr(gv, true); gv } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 764021983e9..0799a388a8b 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -20,7 +20,7 @@ use rustc::mir::tcx::PlaceTy; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf, Size}; use rustc::ty::cast::{CastTy, IntTy}; -use rustc::ty::subst::{Kind, Substs, Subst}; +use rustc::ty::subst::{Kind, Substs}; use rustc_apfloat::{ieee, Float, Status}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use base; @@ -658,8 +658,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.fn_sig(def_id) - .subst(tcx, substs.substs).input(0); + let input = substs.closure_sig(def_id, tcx).input(0); let input = tcx.erase_late_bound_regions_and_normalize(&input); let substs = tcx.mk_substs([operand.ty, input] .iter().cloned().map(Kind::from)); diff --git a/src/librustc_trans_utils/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs index 66833a1a7c2..d586d1ac315 100644 --- a/src/librustc_trans_utils/monomorphize.rs +++ b/src/librustc_trans_utils/monomorphize.rs @@ -12,7 +12,7 @@ use rustc::hir::def_id::DefId; use rustc::middle::lang_items::DropInPlaceFnLangItem; use rustc::traits; use rustc::ty::adjustment::CustomCoerceUnsized; -use rustc::ty::subst::{Kind, Subst}; +use rustc::ty::subst::Kind; use rustc::ty::{self, Ty, TyCtxt}; pub use rustc::ty::Instance; @@ -34,7 +34,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( let self_ty = tcx.mk_closure_from_closure_substs( closure_did, substs); - let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs); + let sig = substs.closure_sig(closure_did, tcx); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 8f409b68752..df1694a6010 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -16,7 +16,6 @@ use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty}; -use rustc::ty::subst::Subst; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use syntax::abi; use syntax::symbol::Symbol; @@ -109,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id, substs).is_none() { - let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs); + let closure_ty = self.closure_sig(def_id, substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 3e725d7ef41..dc5d3141d4c 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -74,7 +74,6 @@ use rustc::ty::{self, LvaluePreference, TypeAndMut, use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; -use rustc::ty::subst::Subst; use errors::DiagnosticBuilder; use syntax::abi; use syntax::feature_gate; @@ -670,7 +669,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs); + let sig = self.closure_sig(def_id_a, substs_a); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b754c981b21..85b926a707d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1268,15 +1268,23 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, )) } - NodeExpr(&hir::Expr { node: hir::ExprClosure(..), hir_id, .. }) => { - let tables = tcx.typeck_tables_of(def_id); - match tables.node_id_to_type(hir_id).sty { - ty::TyClosure(closure_def_id, closure_substs) => { - assert_eq!(def_id, closure_def_id); - return closure_substs.closure_sig(closure_def_id, tcx); - } - ref t => bug!("closure with non-closure type: {:?}", t), - } + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + // Closure signatures are not like other function + // signatures and cannot be accessed through `fn_sig`. For + // example, a closure signature excludes the `self` + // argument. In any case they are embedded within the + // closure type as part of the `ClosureSubsts`. + // + // To get + // the signature of a closure, you should use the + // `closure_sig` method on the `ClosureSubsts`: + // + // closure_substs.closure_sig(def_id, tcx) + // + // or, inside of an inference context, you can use + // + // infcx.closure_sig(def_id, closure_substs) + bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`"); } x => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index be7bd3d5510..fbff6e83fb9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2521,7 +2521,7 @@ pub struct Span { } impl Span { - fn empty() -> Span { + pub fn empty() -> Span { Span { filename: "".to_string(), loline: 0, locol: 0, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 8c14d1bbe8f..61de5f4bc4c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -65,6 +65,7 @@ r##"<!DOCTYPE html> {before_content} <nav class="sidebar"> + <div class="sidebar-menu">☰</div> {logo} {sidebar} </nav> diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9dc01bb0916..d423e53ca18 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -421,9 +421,19 @@ impl ToJson for IndexItemFunctionType { thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default()); thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> = RefCell::new(Vec::new())); -thread_local!(static USED_ID_MAP: RefCell<FxHashMap<String, usize>> = +thread_local!(pub static USED_ID_MAP: RefCell<FxHashMap<String, usize>> = RefCell::new(init_ids())); +pub fn render_text<F: FnMut(RenderType) -> String>(mut render: F) -> (String, String) { + // Save the state of USED_ID_MAP so it only gets updated once even + // though we're rendering twice. + let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone()); + let hoedown_output = render(RenderType::Hoedown); + USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map); + let pulldown_output = render(RenderType::Pulldown); + (hoedown_output, pulldown_output) +} + fn init_ids() -> FxHashMap<String, usize> { [ "main", @@ -699,7 +709,10 @@ fn print_message(msg: &str, intro_msg: &mut bool, span: &Span, text: &str) { println!("{}", msg); } -fn render_difference(diff: &html_diff::Difference, intro_msg: &mut bool, span: &Span, text: &str) { +pub fn render_difference(diff: &html_diff::Difference, + intro_msg: &mut bool, + span: &Span, + text: &str) { match *diff { html_diff::Difference::NodeType { ref elem, ref opposite_elem } => { print_message(&format!(" {} Types differ: expected: `{}`, found: `{}`", @@ -1853,12 +1866,7 @@ fn render_markdown(w: &mut fmt::Formatter, prefix: &str, scx: &SharedContext) -> fmt::Result { - // Save the state of USED_ID_MAP so it only gets updated once even - // though we're rendering twice. - let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone()); - let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown)); - USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map); - let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown)); + let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, ty))); let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output); differences.retain(|s| { match *s { @@ -3542,6 +3550,7 @@ impl<'a> fmt::Display for Sidebar<'a> { let cx = self.cx; let it = self.item; let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; + let mut should_close = false; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() || it.is_enum() || it.is_mod() || it.is_typedef() @@ -3575,6 +3584,8 @@ impl<'a> fmt::Display for Sidebar<'a> { } } + write!(fmt, "<div class=\"sidebar-elems\">")?; + should_close = true; match it.inner { clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, @@ -3625,6 +3636,10 @@ impl<'a> fmt::Display for Sidebar<'a> { write!(fmt, "<script defer src=\"{path}sidebar-items.js\"></script>", path = relpath)?; } + if should_close { + // Closes sidebar-elems div. + write!(fmt, "</div>")?; + } Ok(()) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index dc8ce627638..06e9cbbdf9a 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -106,6 +106,30 @@ return (elem.offsetParent === null) } + function showSidebar() { + var elems = document.getElementsByClassName("sidebar-elems")[0]; + if (elems) { + elems.style.display = "block"; + } + var sidebar = document.getElementsByClassName('sidebar')[0]; + sidebar.style.position = 'fixed'; + sidebar.style.width = '100%'; + sidebar.style.marginLeft = '0'; + document.getElementsByTagName("body")[0].style.marginTop = '45px'; + } + + function hideSidebar() { + var elems = document.getElementsByClassName("sidebar-elems")[0]; + if (elems) { + elems.style.display = ""; + } + var sidebar = document.getElementsByClassName('sidebar')[0]; + sidebar.style.position = ''; + sidebar.style.width = ''; + sidebar.style.marginLeft = ''; + document.getElementsByTagName("body")[0].style.marginTop = ''; + } + // used for special search precedence var TY_PRIMITIVE = itemTypes.indexOf("primitive"); @@ -119,8 +143,7 @@ map(function(s) { var pair = s.split("="); params[decodeURIComponent(pair[0])] = - typeof pair[1] === "undefined" ? - null : decodeURIComponent(pair[1]); + typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]); }); return params; } @@ -131,6 +154,8 @@ } function highlightSourceLines(ev) { + // If we're in mobile mode, we should add the sidebar in any case. + hideSidebar(); var search = document.getElementById("search"); var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { @@ -1460,7 +1485,7 @@ // delayed sidebar rendering. function initSidebarItems(items) { - var sidebar = document.getElementsByClassName('sidebar')[0]; + var sidebar = document.getElementsByClassName('sidebar-elems')[0]; var current = window.sidebarCurrent; function block(shortty, longty) { @@ -1822,6 +1847,30 @@ } }; } + + var params = getQueryStringParams(); + if (params && params.search) { + addClass(document.getElementById("main"), "hidden"); + var search = document.getElementById("search"); + removeClass(search, "hidden"); + search.innerHTML = '<h3 style="text-align: center;">Loading search results...</h3>'; + } + + var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; + if (sidebar_menu) { + sidebar_menu.onclick = function() { + var sidebar = document.getElementsByClassName('sidebar')[0]; + if (sidebar.style.position === "fixed") { + hideSidebar(); + } else { + showSidebar(); + } + }; + } + + window.onresize = function() { + hideSidebar(); + }; }()); // Sets the focus on the search bar at the top of the page diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 426405e1812..99a0f8c3fb1 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -208,7 +208,7 @@ nav.sub { .sidebar .version { font-size: 15px; text-align: center; - border-bottom: #DDDDDD 1px solid; + border-bottom: 1px solid; overflow-wrap: break-word; word-wrap: break-word; /* deprecated */ word-break: break-word; /* Chrome, non-standard */ @@ -247,8 +247,8 @@ nav.sub { } .sidebar-title { - border-top: 1px solid #777; - border-bottom: 1px solid #777; + border-top: 1px solid; + border-bottom: 1px solid; text-align: center; font-size: 17px; margin-bottom: 5px; @@ -263,6 +263,10 @@ nav.sub { width: 100%; } +.sidebar-menu { + display: none; +} + .content { padding: 15px 0; } @@ -364,7 +368,6 @@ h4 > code, h3 > code, .invisible > code { } .invisible { - background: rgba(0, 0, 0, 0); width: 100%; display: inline-block; } @@ -444,7 +447,6 @@ h4 > code, h3 > code, .invisible > code { .content .fn .where, .content .where.fmt-newline { display: block; - color: #4E4C4C; font-size: 0.8em; } @@ -538,7 +540,6 @@ a { } .search-input:focus { - border-color: #66afe9; border-radius: 2px; border: 0; outline: 0; @@ -560,7 +561,8 @@ a { .content .search-results td:first-child a { padding-right: 10px; } tr.result span.primitive::after { - content: ' (primitive type)'; font-style: italic; color: black; + content: ' (primitive type)'; + font-style: italic; } body.blur > :not(#help) { @@ -697,7 +699,6 @@ a.test-arrow:hover{ font-weight: 300; position: absolute; left: -23px; - color: #999; top: 0; } @@ -823,7 +824,7 @@ span.since { position: static; } - .sidebar .location { + .sidebar > .location { float: right; margin: 0px; margin-top: 2px; @@ -843,16 +844,33 @@ span.since { margin-top: 5px; margin-bottom: 5px; float: left; + margin-left: 50px; } - nav.sub { - margin: 0 auto; + .sidebar-menu { + position: absolute; + font-size: 2rem; + cursor: pointer; + margin-top: 2px; + display: block; } - .sidebar .block { + .sidebar-elems { + background-color: #F1F1F1; + position: fixed; + z-index: 1; + left: 0; + top: 45px; + bottom: 0; + overflow-y: auto; + border-right: 1px solid #000; display: none; } + nav.sub { + margin: 0 auto; + } + .content { margin-left: 0px; } @@ -904,8 +922,6 @@ span.since { .tooltip .tooltiptext { width: 120px; display: none; - background-color: black; - color: #fff; text-align: center; padding: 5px 3px; border-radius: 6px; @@ -927,13 +943,10 @@ span.since { margin-top: -5px; border-width: 5px; border-style: solid; - border-color: transparent black transparent transparent; } .important-traits .tooltip .tooltiptext { - background-color: white; - color: black; - border: 1px solid #000; + border: 1px solid; } pre.rust { @@ -953,22 +966,21 @@ pre.rust { float: left; width: 33.3%; text-align: center; - border-bottom: 1px solid #ccc; + border-bottom: 1px solid; font-size: 18px; cursor: pointer; } #titles > div.selected { - border-bottom: 3px solid #0078ee; + border-bottom: 3px solid; } #titles > div:hover { - border-bottom: 3px solid #0089ff; + border-bottom: 3px solid; } #titles > div > div.count { display: inline-block; - color: #888; font-size: 16px; } @@ -995,7 +1007,6 @@ h4 > .important-traits { position: fixed; width: 100vw; height: 100vh; - background-color: rgba(0,0,0,0.3); z-index: 10000; top: 0; left: 0; @@ -1005,13 +1016,12 @@ h4 > .important-traits { display: block; max-width: 60%; min-width: 200px; - background-color: #eee; padding: 8px; top: 40%; position: absolute; left: 50%; transform: translate(-50%, -40%); - border: 1px solid #999; + border: 1px solid; border-radius: 4px; border-top-right-radius: 0; } @@ -1038,35 +1048,24 @@ h3.important { right: -25px; top: -1px; font-size: 18px; - background-color: #eee; width: 25px; padding-right: 2px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; text-align: center; - border: 1px solid #999; + border: 1px solid; border-right: 0; cursor: pointer; } -.modal-content > .close:hover { - background-color: #ff1f1f; - color: white; -} - .modal-content > .whiter { height: 25px; position: absolute; width: 3px; - background-color: #eee; right: -2px; top: 0px; } -.modal-content > .close:hover + .whiter { - background-color: #ff1f1f; -} - #main > div.important-traits { position: absolute; left: -24px; diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index cb19034bf06..5cace837a55 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -31,6 +31,10 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t background-color: white; } +.invisible { + background: rgba(0, 0, 0, 0); +} + .docblock code, .docblock-short code { background-color: #F5F5F5; } @@ -56,6 +60,15 @@ pre { color: #333; } +.sidebar .version { + border-bottom-color: #DDD; +} + +.sidebar-title { + border-top-color: #777; + border-bottom-color: #777; +} + .block a:hover { background: #F5F5F5; } @@ -89,6 +102,12 @@ pre { background: #FDFFD3; } +.content .method .where, +.content .fn .where, +.content .where.fmt-newline { + color: #4E4C4C; +} + .content .highlighted { color: #000 !important; background-color: #ccc; @@ -152,12 +171,20 @@ a.test-arrow { color: #f5f5f5; } +.collapse-toggle { + color: #999; +} + .search-input { color: #555; box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent; background-color: white; } +.search-input:focus { + border-color: #66afe9; +} + .stab.unstable { background: #FFF5D6; border-color: #FFC600; } .stab.deprecated { background: #F3DFFF; border-color: #7F0087; } .stab.portability { background: #C4ECFF; border-color: #7BA5DB; } @@ -176,6 +203,10 @@ a.test-arrow { color: grey; } +tr.result span.primitive::after { + color: black; +} + .line-numbers :target { background-color: transparent; } /* Code highlighting */ @@ -241,3 +272,61 @@ pre.ignore:hover, .information:hover + pre.ignore { .search-failed > a { color: #0089ff; } + +.tooltip .tooltiptext { + background-color: black; + color: #fff; +} + +.tooltip .tooltiptext::after { + border-color: transparent black transparent transparent; +} + +.important-traits .tooltip .tooltiptext { + background-color: white; + color: black; + border-color: black; +} + +#titles > div { + border-bottom-color: #ccc; +} + +#titles > div.selected { + border-bottom-color: #0078ee; +} + +#titles > div:hover { + border-bottom-color: #0089ff; +} + +#titles > div > div.count { + color: #888; +} + +.modal { + background-color: rgba(0,0,0,0.3); +} + +.modal-content { + background-color: #eee; + border-color: #999; +} + +.modal-content > .close { + background-color: #eee; + border-color: #999; +} + +.modal-content > .close:hover { + background-color: #ff1f1f; + color: white; +} + +.modal-content > .whiter { + background-color: #eee; +} + +.modal-content > .close:hover + .whiter { + background-color: #ff1f1f; +} diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index fe6bd985bb6..9b94e9918f8 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,10 +19,15 @@ use rustc::session::search_paths::SearchPaths; use rustc::session::config::Externs; use syntax::codemap::DUMMY_SP; +use clean::Span; + use externalfiles::{ExternalHtml, LoadStringError, load_string}; -use html::render::reset_ids; +use html_diff; + +use html::render::{render_text, reset_ids}; use html::escape::Escape; +use html::render::render_difference; use html::markdown; use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code}; use html::markdown::RenderType; @@ -52,6 +57,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, external_html: &ExternalHtml, include_toc: bool, render_type: RenderType) -> isize { + // Span used for markdown hoedown/pulldown differences. + let mut span = Span::empty(); + span.filename = input.to_owned(); + let input_p = Path::new(input); output.push(input_p.file_stem().unwrap()); output.set_extension("html"); @@ -89,12 +98,36 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, reset_ids(false); - let rendered = if include_toc { - format!("{}", MarkdownWithToc(text, render_type)) + let (hoedown_output, pulldown_output) = if include_toc { + // Save the state of USED_ID_MAP so it only gets updated once even + // though we're rendering twice. + render_text(|ty| format!("{}", MarkdownWithToc(text, ty))) } else { - format!("{}", Markdown(text, render_type)) + // Save the state of USED_ID_MAP so it only gets updated once even + // though we're rendering twice. + render_text(|ty| format!("{}", Markdown(text, ty))) }; + let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output); + differences.retain(|s| { + match *s { + html_diff::Difference::NodeText { ref elem_text, + ref opposite_elem_text, + .. } + if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => { + false + } + _ => true, + } + }); + + if !differences.is_empty() { + let mut intro_msg = false; + for diff in differences { + render_difference(&diff, &mut intro_msg, &span, text); + } + } + let err = write!( &mut out, r#"<!DOCTYPE html> @@ -126,16 +159,16 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, css = css, in_header = external_html.in_header, before_content = external_html.before_content, - text = rendered, + text = if render_type == RenderType::Pulldown { pulldown_output } else { hoedown_output }, after_content = external_html.after_content, - ); + ); match err { Err(e) => { eprintln!("rustdoc: cannot write to `{}`: {}", output.display(), e); 6 } - Ok(_) => 0 + Ok(_) => 0, } } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index b07733d3c80..f40aed2478a 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -211,6 +211,115 @@ pub struct DirBuilder { recursive: bool, } +/// Read the entire contents of a file into a bytes vector. +/// +/// This is a convenience function for using [`File::open`] and [`read_to_end`] +/// with fewer imports and without an intermediate variable. +/// +/// [`File::open`]: struct.File.html#method.open +/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end +/// +/// # Errors +/// +/// This function will return an error if `path` does not already exist. +/// Other errors may also be returned according to [`OpenOptions::open`]. +/// +/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open +/// +/// It will also return an error if it encounters while reading an error +/// of a kind other than [`ErrorKind::Interrupted`]. +/// +/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// use std::net::SocketAddr; +/// +/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> { +/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { + let mut bytes = Vec::new(); + File::open(path)?.read_to_end(&mut bytes)?; + Ok(bytes) +} + +/// Read the entire contents of a file into a string. +/// +/// This is a convenience function for using [`File::open`] and [`read_to_string`] +/// with fewer imports and without an intermediate variable. +/// +/// [`File::open`]: struct.File.html#method.open +/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string +/// +/// # Errors +/// +/// This function will return an error if `path` does not already exist. +/// Other errors may also be returned according to [`OpenOptions::open`]. +/// +/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open +/// +/// It will also return an error if it encounters while reading an error +/// of a kind other than [`ErrorKind::Interrupted`], +/// or if the contents of the file are not valid UTF-8. +/// +/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// use std::net::SocketAddr; +/// +/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> { +/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> { + let mut string = String::new(); + File::open(path)?.read_to_string(&mut string)?; + Ok(string) +} + +/// Write a slice as the entire contents of a file. +/// +/// This function will create a file if it does not exist, +/// and will entirely replace its contents if it does. +/// +/// This is a convenience function for using [`File::create`] and [`write_all`] +/// with fewer imports. +/// +/// [`File::create`]: struct.File.html#method.create +/// [`write_all`]: ../io/trait.Write.html#method.write_all +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_read_write)] +/// +/// use std::fs; +/// +/// # fn foo() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Lorem ipsum")?; +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "fs_read_write", issue = "46588")] +pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { + File::create(path)?.write_all(contents.as_ref()) +} + impl File { /// Attempts to open a file in read-only mode. /// @@ -1912,7 +2021,9 @@ mod tests { ) } #[cfg(unix)] - macro_rules! error { ($e:expr, $s:expr) => ( + macro_rules! error { ($e:expr, $s:expr) => ( error_contains!($e, $s) ) } + + macro_rules! error_contains { ($e:expr, $s:expr) => ( match $e { Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Err(ref err) => assert!(err.to_string().contains($s), @@ -2922,6 +3033,27 @@ mod tests { } #[test] + fn write_then_read() { + let mut bytes = [0; 1024]; + StdRng::new().unwrap().fill_bytes(&mut bytes); + + let tmpdir = tmpdir(); + + check!(fs::write(&tmpdir.join("test"), &bytes[..])); + let v = check!(fs::read(&tmpdir.join("test"))); + assert!(v == &bytes[..]); + + check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF])); + error_contains!(fs::read_string(&tmpdir.join("not-utf8")), + "stream did not contain valid UTF-8"); + + let s = "𐁁𐀓𐀠𐀴𐀍"; + check!(fs::write(&tmpdir.join("utf8"), s.as_bytes())); + let string = check!(fs::read_string(&tmpdir.join("utf8"))); + assert_eq!(string, s); + } + + #[test] fn file_try_clone() { let tmpdir = tmpdir(); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index bf177ac7f2c..12e6231136e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -260,6 +260,7 @@ #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(fs_read_write)] #![feature(fixed_size_array)] #![feature(float_from_str_radix)] #![feature(fn_traits)] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b36473d9b75..de46fedaebb 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -631,7 +631,7 @@ pub mod builtin { #[macro_export] macro_rules! module_path { () => ({ /* compiler built-in */ }) } - /// Boolean evaluation of configuration flags. + /// Boolean evaluation of configuration flags, at compile-time. /// /// In addition to the `#[cfg]` attribute, this macro is provided to allow /// boolean expression evaluation of configuration flags. This frequently diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d4b54e896ab..22cef25320e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -284,10 +284,6 @@ declare_features! ( // Allows all literals in attribute lists and values of key-value pairs. (active, attr_literals, "1.13.0", Some(34981)), - // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI - (active, abi_sysv64, "1.13.0", Some(36167)), - // Allows untagged unions `union U { ... }` (active, untagged_unions, "1.13.0", Some(32836)), @@ -520,6 +516,9 @@ declare_features! ( (accepted, rvalue_static_promotion, "1.21.0", Some(38865)), // Allow Drop types in constants (RFC 1440) (accepted, drop_types_in_const, "1.22.0", Some(33156)), + // Allows the sysV64 ABI to be specified on all platforms + // instead of just the platforms on which it is the C ABI + (accepted, abi_sysv64, "1.24.0", Some(36167)), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -718,6 +717,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_regions", Normal, Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_regions]` attribute \ + is just used for rustc unit tests \ + and will never be stable", + cfg_fn!(rustc_attrs))), ("rustc_error", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "the `#[rustc_error]` attribute \ @@ -1246,10 +1251,6 @@ impl<'a> PostExpansionVisitor<'a> { gate_feature_post!(&self, unboxed_closures, span, "rust-call ABI is subject to change"); }, - Abi::SysV64 => { - gate_feature_post!(&self, abi_sysv64, span, - "sysv64 ABI is experimental and subject to change"); - }, Abi::PtxKernel => { gate_feature_post!(&self, abi_ptx, span, "PTX ABIs are experimental and subject to change"); @@ -1272,6 +1273,7 @@ impl<'a> PostExpansionVisitor<'a> { Abi::Fastcall | Abi::Aapcs | Abi::Win64 | + Abi::SysV64 | Abi::Rust | Abi::C | Abi::System => {} diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 6f20104dda5..d9c33fa50bd 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -14,7 +14,7 @@ use codemap::{CodeMap, FilePathMapping}; use errors::{FatalError, DiagnosticBuilder}; use parse::{token, ParseSess}; use str::char_at; -use symbol::{Symbol, keywords}; +use symbol::Symbol; use std_unicode::property::Pattern_White_Space; use std::borrow::Cow; @@ -1296,18 +1296,6 @@ impl<'a> StringReader<'a> { self.mk_ident(&format!("'{}", lifetime_name)) }); - // Conjure up a "keyword checking ident" to make sure that - // the lifetime name is not a keyword. - let keyword_checking_ident = self.with_str_from(start, |lifetime_name| { - self.mk_ident(lifetime_name) - }); - let keyword_checking_token = &token::Ident(keyword_checking_ident); - let last_bpos = self.pos; - if keyword_checking_token.is_reserved_ident() && - !keyword_checking_token.is_keyword(keywords::Static) { - self.err_span_(start, last_bpos, "lifetimes cannot use keyword names"); - } - return Ok(token::Lifetime(ident)); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2461e65585f..726db733482 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5995,7 +5995,7 @@ impl<'a> Parser<'a> { match any_disr { Some(disr_span) if !all_nullary => self.span_err(disr_span, - "discriminator values can only be used with a c-like enum"), + "discriminator values can only be used with a field-less enum"), _ => () } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index bf059cac891..ec652b5607e 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -503,6 +503,8 @@ pub enum NonNarrowChar { ZeroWidth(BytePos), /// Represents a wide (fullwidth) character Wide(BytePos), + /// Represents a tab character, represented visually with a width of 4 characters + Tab(BytePos), } impl NonNarrowChar { @@ -510,6 +512,7 @@ impl NonNarrowChar { match width { 0 => NonNarrowChar::ZeroWidth(pos), 2 => NonNarrowChar::Wide(pos), + 4 => NonNarrowChar::Tab(pos), _ => panic!("width {} given for non-narrow character", width), } } @@ -518,7 +521,8 @@ impl NonNarrowChar { pub fn pos(&self) -> BytePos { match *self { NonNarrowChar::ZeroWidth(p) | - NonNarrowChar::Wide(p) => p, + NonNarrowChar::Wide(p) | + NonNarrowChar::Tab(p) => p, } } @@ -527,6 +531,7 @@ impl NonNarrowChar { match *self { NonNarrowChar::ZeroWidth(_) => 0, NonNarrowChar::Wide(_) => 2, + NonNarrowChar::Tab(_) => 4, } } } @@ -538,6 +543,7 @@ impl Add<BytePos> for NonNarrowChar { match self { NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs), NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs), + NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs), } } } @@ -549,6 +555,7 @@ impl Sub<BytePos> for NonNarrowChar { match self { NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs), NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs), + NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs), } } } @@ -868,8 +875,10 @@ impl FileMap { pub fn record_width(&self, pos: BytePos, ch: char) { let width = match ch { - '\t' | '\n' => - // Tabs will consume one column. + '\t' => + // Tabs will consume 4 columns. + 4, + '\n' => // Make newlines take one column so that displayed spans can point them. 1, ch => diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 69ddd560213..aafdd696b74 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -35,6 +35,10 @@ impl Ident { Ident::with_empty_ctxt(Symbol::intern(string)) } + pub fn without_first_quote(&self) -> Ident { + Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt } + } + pub fn modern(self) -> Ident { Ident { name: self.name, ctxt: self.ctxt.modern() } } @@ -123,7 +127,12 @@ impl<'a> From<&'a str> for Symbol { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}({})", self, self.0) + let is_gensymed = with_interner(|interner| interner.is_gensymed(*self)); + if is_gensymed { + write!(f, "{}({})", self, self.0) + } else { + write!(f, "{}", self) + } } } @@ -201,6 +210,10 @@ impl Interner { Symbol(!0 - self.gensyms.len() as u32 + 1) } + fn is_gensymed(&mut self, symbol: Symbol) -> bool { + symbol.0 as usize >= self.strings.len() + } + pub fn get(&self, symbol: Symbol) -> &str { match self.strings.get(symbol.0 as usize) { Some(ref string) => string, @@ -428,4 +441,10 @@ mod tests { // gensym of *existing* string gets new number: assert_eq!(i.gensym("dog"), Symbol(4294967293)); } + + #[test] + fn without_first_quote_test() { + let i = Ident::from_str("'break"); + assert_eq!(i.without_first_quote().name, keywords::Break.name()); + } } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 1797e19c549..072a9144f17 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -970,7 +970,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, std::set<GlobalValue::GUID> ExportedGUIDs; for (auto &List : Ret->Index) { for (auto &GVS: List.second) { - if (!GlobalValue::isExternalLinkage(GVS->linkage())) + if (GlobalValue::isLocalLinkage(GVS->linkage())) continue; auto GUID = GVS->getOriginalName(); if (!DeadSymbols.count(GUID)) diff --git a/src/test/codegen/abi-sysv64.rs b/src/test/codegen/abi-sysv64.rs index 4f6a50eab49..920f5cbcca3 100644 --- a/src/test/codegen/abi-sysv64.rs +++ b/src/test/codegen/abi-sysv64.rs @@ -18,7 +18,6 @@ // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] -#![feature(abi_sysv64)] // CHECK: define x86_64_sysvcc i64 @has_sysv64_abi #[no_mangle] diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs index 3f5725029d8..fa80a2efdf8 100644 --- a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs @@ -13,7 +13,7 @@ fn cplusplus_mode(x: isize) -> &'static isize { &x //[ast]~ ERROR `x` does not live long enough - //[mir]~^ ERROR borrowed value does not live long enough } +//[mir]~^ ERROR borrowed value does not live long enough fn main() {} diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs index 7009c6f33e6..78f0d321e0d 100644 --- a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs @@ -14,9 +14,9 @@ fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) { let mut z = (0, 0); *x = Some(&mut z.1); //[ast]~ ERROR [E0597] - //[mir]~^ ERROR [E0597] panic!("catch me for a dangling pointer!") } +//[mir]~^ ERROR [E0597] fn main() { cplusplus_mode_exceptionally_unsafe(&mut None); diff --git a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs index c46bcbb32b9..2bd6f75df1b 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z borrowck=mir + #![feature(box_syntax)] fn call_f<F:FnOnce() -> isize>(f: F) -> isize { @@ -18,5 +21,6 @@ fn main() { let t: Box<_> = box 3; call_f(move|| { *t + 1 }); - call_f(move|| { *t + 1 }); //~ ERROR capture of moved value + call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value + //[mir]~^ ERROR use of moved value } diff --git a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs index 6896d166e7a..63bb04a0e4c 100644 --- a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs +++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs @@ -23,15 +23,9 @@ fn main() { 1 => { addr = &mut x; } //[ast]~ ERROR [E0499] //[mir]~^ ERROR [E0499] 2 => { addr = &mut x; } //[ast]~ ERROR [E0499] - //[mir]~^ ERROR [E0506] - //[mir]~| ERROR [E0499] - //[mir]~| ERROR [E0499] + //[mir]~^ ERROR [E0499] _ => { addr = &mut x; } //[ast]~ ERROR [E0499] - //[mir]~^ ERROR [E0506] - //[mir]~| ERROR [E0499] - //[mir]~| ERROR [E0499] + //[mir]~^ ERROR [E0499] } } } - - diff --git a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs index f2e6d51d064..df0a05dfaee 100644 --- a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-test will be fixed later // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs index 975de8b6c41..0241b3870c7 100644 --- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs @@ -52,12 +52,12 @@ fn main() { { let ra = &u.a; let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable } { let ra = &u.a; u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed } // Mut borrow, same field { @@ -84,22 +84,23 @@ fn main() { { let rma = &mut u.a; let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable } { let ra = &mut u.a; let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed + } { let rma = &mut u.a; let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time } { let rma = &mut u.a; u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed - // FIXME Error for MIR (needs support for union) + //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed } } } diff --git a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs index 304a41c14ed..94877b27d58 100644 --- a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs @@ -1,3 +1,4 @@ + // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -22,7 +23,7 @@ fn main() { println!("t[0]: {}", t[0]); a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) - // FIXME Error for MIR (error missed) + //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/compile-fail/issue-10412.rs index d723d94c02c..ee553730a35 100644 --- a/src/test/parse-fail/issue-10412.rs +++ b/src/test/compile-fail/issue-10412.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only -Z continue-parse-after-error - - trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names - fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR lifetimes cannot use keyword names + fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names } impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names //~^ ERROR lifetimes cannot use keyword names + //~| ERROR missing lifetime specifier fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names vec![1] } diff --git a/src/test/compile-fail/issue-25579.rs b/src/test/compile-fail/issue-25579.rs index 9e12d5b5de1..5f5a58ed759 100644 --- a/src/test/compile-fail/issue-25579.rs +++ b/src/test/compile-fail/issue-25579.rs @@ -20,13 +20,9 @@ fn causes_ice(mut l: &mut Sexpression) { loop { match l { &mut Sexpression::Num(ref mut n) => {}, &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499] - //[mir]~^ ERROR [E0506] - //[mir]~| ERROR [E0499] + //[mir]~^ ERROR [E0499] l = &mut **expr; //[ast]~ ERROR [E0506] //[mir]~^ ERROR [E0506] - //[mir]~| ERROR [E0506] - //[mir]~| ERROR [E0499] - //[mir]~| ERROR [E0499] } }} } diff --git a/src/test/compile-fail/no-core-gated.rs b/src/test/compile-fail/issue-46311.rs index 27f8fda98ab..82f55f2c142 100644 --- a/src/test/compile-fail/no-core-gated.rs +++ b/src/test/compile-fail/issue-46311.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-no_core - -#![no_core] //~ ERROR no_core is experimental - -fn main() {} +fn main() { + 'break: loop { //~ ERROR invalid label name `'break` + } +} diff --git a/src/test/parse-fail/lifetime-no-keyword.rs b/src/test/compile-fail/lifetime-no-keyword.rs index a8771ae93af..d583c4fc6c6 100644 --- a/src/test/parse-fail/lifetime-no-keyword.rs +++ b/src/test/compile-fail/lifetime-no-keyword.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only -Z continue-parse-after-error - fn foo<'a>(a: &'a isize) { } fn bar(a: &'static isize) { } -fn baz(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names -fn zab(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names - +fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names +fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names fn main() { } diff --git a/src/test/compile-fail/region-borrow-params-issue-29793-big.rs b/src/test/compile-fail/region-borrow-params-issue-29793-big.rs index 887f7836ee1..a4dc00bd2b1 100644 --- a/src/test/compile-fail/region-borrow-params-issue-29793-big.rs +++ b/src/test/compile-fail/region-borrow-params-issue-29793-big.rs @@ -16,6 +16,10 @@ // behavior (because the improperly accepted closure was actually // able to be invoked). +// ignore-tidy-linelength +// revisions: ast mir +//[mir]compile-flags: -Z borrowck=mir + struct WrapA<F>(Option<F>); impl<F> WrapA<F> { @@ -75,9 +79,11 @@ impl<F, T> WrapA<F> fn main() { let mut w = WrapA::new().set(|x: usize, y: usize| { WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) - //~^ ERROR `x` does not live long enough - //~| ERROR `y` does not live long enough + //[ast]~^ ERROR `x` does not live long enough + //[ast]~| ERROR `y` does not live long enough }); + //[mir]~^ ERROR borrowed value does not live long enough + //[mir]~| ERROR borrowed value does not live long enough w.handle(); // This works // w.handle_ref(); // This doesn't diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs index de695e72d07..9de8ca196f8 100644 --- a/src/test/compile-fail/regions-static-bound.rs +++ b/src/test/compile-fail/regions-static-bound.rs @@ -8,17 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ll nll +//[nll] compile-flags: -Znll -Zborrowck=mir + fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t } fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () where 'a: 'b, 'b: 'static { t } fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { - t //~ ERROR E0312 + t //[ll]~ ERROR E0312 + //[nll]~^ WARNING not reporting region error due to -Znll + //[nll]~| ERROR free region `'a` does not outlive free region `'static` } fn error(u: &(), v: &()) { - static_id(&u); //~ ERROR cannot infer an appropriate lifetime - static_id_indirect(&v); //~ ERROR cannot infer an appropriate lifetime + static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime + //[nll]~^ WARNING not reporting region error due to -Znll + static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime + //[nll]~^ WARNING not reporting region error due to -Znll + + // FIXME(#45827) -- MIR type checker shortcomings mean we don't + // see these errors (yet) in nll mode. } fn main() {} diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index a62d84fedf3..da8a62a9765 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 4abc77e0ab6..d8a87da5918 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -27,16 +27,14 @@ // Change closure body --------------------------------------------------------- #[cfg(cfail1)] -fn change_closure_body() { +pub fn change_closure_body() { let _ = || 1u32; } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_closure_body() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn change_closure_body() { let _ = || 3u32; } @@ -44,17 +42,15 @@ fn change_closure_body() { // Add parameter --------------------------------------------------------------- #[cfg(cfail1)] -fn add_parameter() { +pub fn add_parameter() { let x = 0u32; let _ = || x + 1; } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_parameter() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn add_parameter() { let x = 0u32; let _ = |x: u32| x + 1; } @@ -63,16 +59,14 @@ fn add_parameter() { // Change parameter pattern ---------------------------------------------------- #[cfg(cfail1)] -fn change_parameter_pattern() { +pub fn change_parameter_pattern() { let _ = |x: &u32| x; } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_parameter_pattern() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_parameter_pattern() { let _ = |&x: &u32| x; } @@ -80,16 +74,14 @@ fn change_parameter_pattern() { // Add `move` to closure ------------------------------------------------------- #[cfg(cfail1)] -fn add_move() { +pub fn add_move() { let _ = || 1; } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_move() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_move() { let _ = move || 1; } @@ -97,17 +89,15 @@ fn add_move() { // Add type ascription to parameter -------------------------------------------- #[cfg(cfail1)] -fn add_type_ascription_to_parameter() { +pub fn add_type_ascription_to_parameter() { let closure = |x| x + 1u32; let _: u32 = closure(1); } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_type_ascription_to_parameter() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; let _: u32 = closure(1); } @@ -116,17 +106,15 @@ fn add_type_ascription_to_parameter() { // Change parameter type ------------------------------------------------------- #[cfg(cfail1)] -fn change_parameter_type() { +pub fn change_parameter_type() { let closure = |x: u32| (x as u64) + 1; let _ = closure(1); } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_parameter_type() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; let _ = closure(1); } diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 496ae4276f8..47f5a2d2bbe 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index f38d1864630..541261f1d80 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index dbb7aca1924..02746785856 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -23,7 +23,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index 985c064f6a0..a796c87f19b 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -10,7 +10,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 7ccb452b7ed..bcdd5661e71 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 763b0cd05d4..105afd30d28 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -27,7 +27,7 @@ // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_body() { +pub fn change_loop_body() { let mut _x = 0; for _ in 0..1 { _x = 1; @@ -36,11 +36,9 @@ fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_body() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_body() { let mut _x = 0; for _ in 0..1 { _x = 2; @@ -52,7 +50,7 @@ fn change_loop_body() { // Change iteration variable name ---------------------------------------------- #[cfg(cfail1)] -fn change_iteration_variable_name() { +pub fn change_iteration_variable_name() { let mut _x = 0; for _i in 0..1 { _x = 1; @@ -61,11 +59,9 @@ fn change_iteration_variable_name() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_iteration_variable_name() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_iteration_variable_name() { let mut _x = 0; for _a in 0..1 { _x = 1; @@ -77,7 +73,7 @@ fn change_iteration_variable_name() { // Change iteration variable pattern ------------------------------------------- #[cfg(cfail1)] -fn change_iteration_variable_pattern() { +pub fn change_iteration_variable_pattern() { let mut _x = 0; for _i in &[0, 1, 2] { _x = 1; @@ -86,11 +82,9 @@ fn change_iteration_variable_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_iteration_variable_pattern() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_iteration_variable_pattern() { let mut _x = 0; for &_i in &[0, 1, 2] { _x = 1; @@ -102,7 +96,7 @@ fn change_iteration_variable_pattern() { // Change iterable ------------------------------------------------------------- #[cfg(cfail1)] -fn change_iterable() { +pub fn change_iterable() { let mut _x = 0; for _ in &[0, 1, 2] { _x = 1; @@ -111,11 +105,9 @@ fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_iterable() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_iterable() { let mut _x = 0; for _ in &[0, 1, 3] { _x = 1; @@ -127,7 +119,7 @@ fn change_iterable() { // Add break ------------------------------------------------------------------- #[cfg(cfail1)] -fn add_break() { +pub fn add_break() { let mut _x = 0; for _ in 0..1 { _x = 1; @@ -135,11 +127,9 @@ fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn add_break() { let mut _x = 0; for _ in 0..1 { _x = 1; @@ -151,7 +141,7 @@ fn add_break() { // Add loop label -------------------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label() { +pub fn add_loop_label() { let mut _x = 0; for _ in 0..1 { _x = 1; @@ -160,11 +150,9 @@ fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; @@ -176,7 +164,7 @@ fn add_loop_label() { // Add loop label to break ----------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_break() { +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; @@ -185,11 +173,9 @@ fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; @@ -201,7 +187,7 @@ fn add_loop_label_to_break() { // Change break label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_break_label() { +pub fn change_break_label() { let mut _x = 0; 'outer: for _ in 0..1 { 'inner: for _ in 0..1 { @@ -212,11 +198,9 @@ fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_break_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_break_label() { let mut _x = 0; 'outer: for _ in 0..1 { 'inner: for _ in 0..1 { @@ -230,7 +214,7 @@ fn change_break_label() { // Add loop label to continue -------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_continue() { +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; @@ -239,11 +223,9 @@ fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_continue() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; @@ -255,7 +237,7 @@ fn add_loop_label_to_continue() { // Change continue label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_continue_label() { +pub fn change_continue_label() { let mut _x = 0; 'outer: for _ in 0..1 { 'inner: for _ in 0..1 { @@ -266,11 +248,9 @@ fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_label() { let mut _x = 0; 'outer: for _ in 0..1 { 'inner: for _ in 0..1 { @@ -284,7 +264,7 @@ fn change_continue_label() { // Change continue to break ---------------------------------------------------- #[cfg(cfail1)] -fn change_continue_to_break() { +pub fn change_continue_to_break() { let mut _x = 0; for _ in 0..1 { _x = 1; @@ -293,11 +273,9 @@ fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_to_break() { let mut _x = 0; for _ in 0..1 { _x = 1; diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index b3eb566367c..abe0586efcd 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] @@ -26,245 +26,253 @@ #![feature(intrinsics)] #![feature(linkage)] #![feature(rustc_attrs)] -#![crate_type="rlib"] +#![crate_type = "rlib"] // Add Parameter --------------------------------------------------------------- #[cfg(cfail1)] -fn add_parameter() {} +pub fn add_parameter() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn add_parameter(p: i32) {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub fn add_parameter(p: i32) {} // Add Return Type ------------------------------------------------------------- #[cfg(cfail1)] -fn add_return_type() {} +pub fn add_return_type() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn add_return_type() -> () {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] +pub fn add_return_type() -> () {} // Change Parameter Type ------------------------------------------------------- #[cfg(cfail1)] -fn type_of_parameter(p: i32) {} +pub fn type_of_parameter(p: i32) {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn type_of_parameter(p: i64) {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub fn type_of_parameter(p: i64) {} // Change Parameter Type Reference --------------------------------------------- #[cfg(cfail1)] -fn type_of_parameter_ref(p: &i32) {} +pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn type_of_parameter_ref(p: &mut i32) {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub fn type_of_parameter_ref(p: &mut i32) {} // Change Parameter Order ------------------------------------------------------ #[cfg(cfail1)] -fn order_of_parameters(p1: i32, p2: i64) {} +pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn order_of_parameters(p2: i64, p1: i32) {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub fn order_of_parameters(p2: i64, p1: i32) {} // Unsafe ---------------------------------------------------------------------- #[cfg(cfail1)] -fn make_unsafe() {} +pub fn make_unsafe() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -unsafe fn make_unsafe() {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub unsafe fn make_unsafe() {} // Extern ---------------------------------------------------------------------- #[cfg(cfail1)] -fn make_extern() {} +pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -extern fn make_extern() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub extern "C" fn make_extern() {} // Extern C Extern Rust-Intrinsic ---------------------------------------------- #[cfg(cfail1)] -extern "C" fn make_intrinsic() {} +pub extern "C" fn make_intrinsic() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -extern "rust-intrinsic" fn make_intrinsic() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub extern "rust-intrinsic" fn make_intrinsic() {} // Type Parameter -------------------------------------------------------------- #[cfg(cfail1)] -fn type_parameter() {} +pub fn type_parameter() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn type_parameter<T>() {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn type_parameter<T>() {} // Lifetime Parameter ---------------------------------------------------------- #[cfg(cfail1)] -fn lifetime_parameter() {} +pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn lifetime_parameter<'a>() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, GenericsOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn lifetime_parameter<'a>() {} // Trait Bound ----------------------------------------------------------------- #[cfg(cfail1)] -fn trait_bound<T>() {} +pub fn trait_bound<T>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn trait_bound<T: Eq>() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn trait_bound<T: Eq>() {} // Builtin Bound --------------------------------------------------------------- #[cfg(cfail1)] -fn builtin_bound<T>() {} +pub fn builtin_bound<T>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn builtin_bound<T: Send>() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn builtin_bound<T: Send>() {} // Lifetime Bound -------------------------------------------------------------- #[cfg(cfail1)] -fn lifetime_bound<'a, T>() {} +pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn lifetime_bound<'a, T: 'a>() {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn lifetime_bound<'a, T: 'a>() {} // Second Trait Bound ---------------------------------------------------------- #[cfg(cfail1)] -fn second_trait_bound<T: Eq>() {} +pub fn second_trait_bound<T: Eq>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn second_trait_bound<T: Eq + Clone>() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn second_trait_bound<T: Eq + Clone>() {} // Second Builtin Bound -------------------------------------------------------- #[cfg(cfail1)] -fn second_builtin_bound<T: Send>() {} +pub fn second_builtin_bound<T: Send>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn second_builtin_bound<T: Send + Sized>() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn second_builtin_bound<T: Send + Sized>() {} // Second Lifetime Bound ------------------------------------------------------- #[cfg(cfail1)] -fn second_lifetime_bound<'a, 'b, T: 'a>() {} +pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} +#[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")] +#[rustc_clean(cfg = "cfail3")] +pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} // Inline ---------------------------------------------------------------------- #[cfg(cfail1)] -fn inline() {} +pub fn inline() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] #[inline] -fn inline() {} +pub fn inline() {} // Inline Never ---------------------------------------------------------------- #[cfg(cfail1)] #[inline(always)] -fn inline_never() {} +pub fn inline_never() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] #[inline(never)] -fn inline_never() {} +pub fn inline_never() {} // No Mangle ------------------------------------------------------------------- #[cfg(cfail1)] -fn no_mangle() {} +pub fn no_mangle() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] #[no_mangle] -fn no_mangle() {} +pub fn no_mangle() {} // Linkage --------------------------------------------------------------------- #[cfg(cfail1)] -fn linkage() {} +pub fn linkage() {} #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[linkage="weak_odr"] -fn linkage() {} +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] +#[linkage = "weak_odr"] +pub fn linkage() {} // Return Impl Trait ----------------------------------------------------------- #[cfg(cfail1)] -fn return_impl_trait() -> i32 { +pub fn return_impl_trait() -> i32 { 0 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn return_impl_trait() -> impl Clone { +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")] +#[rustc_clean(cfg = "cfail3")] +pub fn return_impl_trait() -> impl Clone { 0 } @@ -272,32 +280,33 @@ fn return_impl_trait() -> impl Clone { // Change Return Impl Trait ---------------------------------------------------- #[cfg(cfail1)] -fn change_return_impl_trait() -> impl Clone { +pub fn change_return_impl_trait() -> impl Clone { 0u32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -fn change_return_impl_trait() -> impl Copy { +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail3")] +pub fn change_return_impl_trait() -> impl Copy { 0u32 } // Change Return Type Indirectly ----------------------------------------------- -struct ReferencedType1; -struct ReferencedType2; +pub struct ReferencedType1; +pub struct ReferencedType2; -mod change_return_type_indirectly { +pub mod change_return_type_indirectly { #[cfg(cfail1)] use super::ReferencedType1 as ReturnType; #[cfg(not(cfail1))] use super::ReferencedType2 as ReturnType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - fn indirect_return_type() -> ReturnType { + #[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] + #[rustc_clean(cfg = "cfail3")] + pub fn indirect_return_type() -> ReturnType { ReturnType {} } } @@ -305,44 +314,49 @@ mod change_return_type_indirectly { // Change Parameter Type Indirectly -------------------------------------------- -mod change_parameter_type_indirectly { +pub mod change_parameter_type_indirectly { #[cfg(cfail1)] use super::ReferencedType1 as ParameterType; #[cfg(not(cfail1))] use super::ReferencedType2 as ParameterType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - fn indirect_parameter_type(p: ParameterType) {} + #[rustc_clean(cfg = "cfail2", + except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")] + #[rustc_clean(cfg = "cfail3")] + pub fn indirect_parameter_type(p: ParameterType) {} } // Change Trait Bound Indirectly ----------------------------------------------- -trait ReferencedTrait1 {} -trait ReferencedTrait2 {} +pub trait ReferencedTrait1 {} +pub trait ReferencedTrait2 {} -mod change_trait_bound_indirectly { +pub mod change_trait_bound_indirectly { #[cfg(cfail1)] use super::ReferencedTrait1 as Trait; #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - fn indirect_trait_bound<T: Trait>(p: T) {} + #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] + #[rustc_clean(cfg = "cfail3")] + pub fn indirect_trait_bound<T: Trait>(p: T) {} } // Change Trait Bound Indirectly In Where Clause ------------------------------- -mod change_trait_bound_indirectly_in_where_clause { +pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(cfail1)] use super::ReferencedTrait1 as Trait; #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - fn indirect_trait_bound_where<T>(p: T) where T: Trait {} + #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")] + #[rustc_clean(cfg = "cfail3")] + pub fn indirect_trait_bound_where<T>(p: T) + where + T: Trait, + { + } } diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index d6878028cfa..426c58c834d 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 715146146f1..e66e239b33c 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index c8c2fa5e8c8..93aba4a3ee1 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index 0947239c573..b93a9656603 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -30,7 +30,7 @@ // Change template ------------------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_template(a: i32) -> i32 { +pub fn change_template(a: i32) -> i32 { let c: i32; unsafe { asm!("add 1, $0" @@ -44,12 +44,10 @@ fn change_template(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_template(a: i32) -> i32 { +pub fn change_template(a: i32) -> i32 { let c: i32; unsafe { asm!("add 2, $0" @@ -67,7 +65,7 @@ fn change_template(a: i32) -> i32 { // Change output ------------------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_output(a: i32) -> i32 { +pub fn change_output(a: i32) -> i32 { let mut _out1: i32 = 0; let mut _out2: i32 = 0; unsafe { @@ -82,12 +80,10 @@ fn change_output(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_output(a: i32) -> i32 { +pub fn change_output(a: i32) -> i32 { let mut _out1: i32 = 0; let mut _out2: i32 = 0; unsafe { @@ -106,7 +102,7 @@ fn change_output(a: i32) -> i32 { // Change input ------------------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_input(_a: i32, _b: i32) -> i32 { +pub fn change_input(_a: i32, _b: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -120,12 +116,10 @@ fn change_input(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_input(_a: i32, _b: i32) -> i32 { +pub fn change_input(_a: i32, _b: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -143,7 +137,7 @@ fn change_input(_a: i32, _b: i32) -> i32 { // Change input constraint ----------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_input_constraint(_a: i32, _b: i32) -> i32 { +pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -157,12 +151,10 @@ fn change_input_constraint(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_input_constraint(_a: i32, _b: i32) -> i32 { +pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -180,7 +172,7 @@ fn change_input_constraint(_a: i32, _b: i32) -> i32 { // Change clobber -------------------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_clobber(_a: i32) -> i32 { +pub fn change_clobber(_a: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -194,12 +186,10 @@ fn change_clobber(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_clobber(_a: i32) -> i32 { +pub fn change_clobber(_a: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -217,7 +207,7 @@ fn change_clobber(_a: i32) -> i32 { // Change options -------------------------------------------------------------- #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_options(_a: i32) -> i32 { +pub fn change_options(_a: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" @@ -231,12 +221,10 @@ fn change_options(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn change_options(_a: i32) -> i32 { +pub fn change_options(_a: i32) -> i32 { let _out; unsafe { asm!("add 1, $0" diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index f3bddc66984..851b13c7055 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index 8d015288757..dcb937fd867 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -27,7 +27,7 @@ // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_body() { +pub fn change_loop_body() { let mut _x = 0; loop { _x = 1; @@ -36,11 +36,9 @@ fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_body() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_body() { let mut _x = 0; loop { _x = 2; @@ -52,7 +50,7 @@ fn change_loop_body() { // Add break ------------------------------------------------------------------- #[cfg(cfail1)] -fn add_break() { +pub fn add_break() { let mut _x = 0; loop { _x = 1; @@ -60,11 +58,9 @@ fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn add_break() { let mut _x = 0; loop { _x = 1; @@ -76,7 +72,7 @@ fn add_break() { // Add loop label -------------------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label() { +pub fn add_loop_label() { let mut _x = 0; loop { _x = 1; @@ -85,11 +81,9 @@ fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label() { let mut _x = 0; 'label: loop { _x = 1; @@ -101,7 +95,7 @@ fn add_loop_label() { // Add loop label to break ----------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_break() { +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: loop { _x = 1; @@ -110,11 +104,9 @@ fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: loop { _x = 1; @@ -126,7 +118,7 @@ fn add_loop_label_to_break() { // Change break label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_break_label() { +pub fn change_break_label() { let mut _x = 0; 'outer: loop { 'inner: loop { @@ -137,11 +129,9 @@ fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_break_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_break_label() { let mut _x = 0; 'outer: loop { 'inner: loop { @@ -155,7 +145,7 @@ fn change_break_label() { // Add loop label to continue -------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_continue() { +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: loop { _x = 1; @@ -164,11 +154,9 @@ fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_continue() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: loop { _x = 1; @@ -180,7 +168,7 @@ fn add_loop_label_to_continue() { // Change continue label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_continue_label() { +pub fn change_continue_label() { let mut _x = 0; 'outer: loop { 'inner: loop { @@ -191,11 +179,9 @@ fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_label() { let mut _x = 0; 'outer: loop { 'inner: loop { @@ -209,7 +195,7 @@ fn change_continue_label() { // Change continue to break ---------------------------------------------------- #[cfg(cfail1)] -fn change_continue_to_break() { +pub fn change_continue_to_break() { let mut _x = 0; loop { _x = 1; @@ -218,11 +204,9 @@ fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_to_break() { let mut _x = 0; loop { _x = 1; diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index 38edd675cc6..263901f4025 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index c76c10f2ab4..2b6a140be32 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -28,155 +28,134 @@ // Indexing expression --------------------------------------------------------- -#[cfg(cfail1)] -pub fn indexing(slice: &[u8]) -> u8 { - slice[100] -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { - slice[100] + #[cfg(cfail1)] + { + slice[100] + } + #[cfg(not(cfail1))] + { + slice[100] + } } // Arithmetic overflow plus ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_plus(val: i32) -> i32 { - val + 1 -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { - val + 1 + #[cfg(cfail1)] + { + val + 1 + } + #[cfg(not(cfail1))] + { + val + 1 + } } // Arithmetic overflow minus ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_minus(val: i32) -> i32 { - val - 1 -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { - val - 1 + #[cfg(cfail1)] + { + val - 1 + } + #[cfg(not(cfail1))] + { + val - 1 + } } // Arithmetic overflow mult ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_mult(val: i32) -> i32 { - val * 2 -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { - val * 2 + #[cfg(cfail1)] + { + val * 2 + } + #[cfg(not(cfail1))] + { + val * 2 + } } // Arithmetic overflow negation ------------------------------------------------ -#[cfg(cfail1)] -pub fn arithmetic_overflow_negation(val: i32) -> i32 { - -val -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { - -val + #[cfg(cfail1)] + { + -val + } + #[cfg(not(cfail1))] + { + -val + } } // Division by zero ------------------------------------------------------------ -#[cfg(cfail1)] -pub fn division_by_zero(val: i32) -> i32 { - 2 / val -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { - 2 / val + #[cfg(cfail1)] + { + 2 / val + } + #[cfg(not(cfail1))] + { + 2 / val + } } // Division by zero ------------------------------------------------------------ -#[cfg(cfail1)] -pub fn mod_by_zero(val: i32) -> i32 { - 2 % val -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { - 2 % val + #[cfg(cfail1)] + { + 2 % val + } + #[cfg(not(cfail1))] + { + 2 % val + } } // shift left ------------------------------------------------------------------ -#[cfg(cfail1)] -pub fn shift_left(val: i32, shift: usize) -> i32 { - val << shift -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { - val << shift + #[cfg(cfail1)] + { + val << shift + } + #[cfg(not(cfail1))] + { + val << shift + } } // shift right ------------------------------------------------------------------ -#[cfg(cfail1)] -pub fn shift_right(val: i32, shift: usize) -> i32 { - val >> shift -} - -#[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { - val >> shift -} - - -// THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION - -// bitwise --------------------------------------------------------------------- -#[cfg(cfail1)] -pub fn bitwise(val: i32) -> i32 { - !val & 0x101010101 | 0x45689 ^ 0x2372382 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn bitwise(val: i32) -> i32 { - !val & 0x101010101 | 0x45689 ^ 0x2372382 -} - - -// logical --------------------------------------------------------------------- -#[cfg(cfail1)] -pub fn logical(val1: bool, val2: bool, val3: bool) -> bool { - val1 && val2 || val3 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn logical(val1: bool, val2: bool, val3: bool) -> bool { - val1 && val2 || val3 + #[cfg(cfail1)] + { + val >> shift + } + #[cfg(not(cfail1))] + { + val >> shift + } } diff --git a/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs b/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs deleted file mode 100644 index 8402da04091..00000000000 --- a/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test case tests the incremental compilation hash (ICH) implementation -// for exprs that can panic at runtime (e.g. because of bounds checking). For -// these expressions an error message containing their source location is -// generated, so their hash must always depend on their location in the source -// code, not just when debuginfo is enabled. - -// As opposed to the panic_exprs.rs test case, this test case checks that things -// behave as expected when overflow checks are off: -// -// - Addition, subtraction, and multiplication do not change the ICH, unless -// the function containing them is marked with rustc_inherit_overflow_checks. -// - Division by zero and bounds checks always influence the ICH - -// The general pattern followed here is: Change one thing between rev1 and rev2 -// and make sure that the hash has changed, then change nothing between rev2 and -// rev3 and make sure that the hash has not changed. - -// must-compile-successfully -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Z force-overflow-checks=off - -#![allow(warnings)] -#![feature(rustc_attrs)] -#![crate_type="rlib"] - - -// Indexing expression --------------------------------------------------------- -#[cfg(cfail1)] -pub fn indexing(slice: &[u8]) -> u8 { - slice[100] -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -pub fn indexing(slice: &[u8]) -> u8 { - slice[100] -} - - -// Arithmetic overflow plus ---------------------------------------------------- -#[cfg(cfail1)] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_plus_inherit(val: i32) -> i32 { - val + 1 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_plus_inherit(val: i32) -> i32 { - val + 1 -} - - -// Arithmetic overflow minus ---------------------------------------------------- -#[cfg(cfail1)] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_minus_inherit(val: i32) -> i32 { - val - 1 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_minus_inherit(val: i32) -> i32 { - val - 1 -} - - -// Arithmetic overflow mult ---------------------------------------------------- -#[cfg(cfail1)] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_mult_inherit(val: i32) -> i32 { - val * 2 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_mult_inherit(val: i32) -> i32 { - val * 2 -} - - -// Arithmetic overflow negation ------------------------------------------------ -#[cfg(cfail1)] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_negation_inherit(val: i32) -> i32 { - -val -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -#[rustc_inherit_overflow_checks] -pub fn arithmetic_overflow_negation_inherit(val: i32) -> i32 { - -val -} - - -// Division by zero ------------------------------------------------------------ -#[cfg(cfail1)] -pub fn division_by_zero(val: i32) -> i32 { - 2 / val -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -pub fn division_by_zero(val: i32) -> i32 { - 2 / val -} - -// Division by zero ------------------------------------------------------------ -#[cfg(cfail1)] -pub fn mod_by_zero(val: i32) -> i32 { - 2 % val -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] -#[rustc_clean(cfg="cfail3")] -pub fn mod_by_zero(val: i32) -> i32 { - 2 % val -} - - - -// THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION - -// bitwise --------------------------------------------------------------------- -#[cfg(cfail1)] -pub fn bitwise(val: i32) -> i32 { - !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn bitwise(val: i32) -> i32 { - !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1 -} - - -// logical --------------------------------------------------------------------- -#[cfg(cfail1)] -pub fn logical(val1: bool, val2: bool, val3: bool) -> bool { - val1 && val2 || val3 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn logical(val1: bool, val2: bool, val3: bool) -> bool { - val1 && val2 || val3 -} - -// Arithmetic overflow plus ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_plus(val: i32) -> i32 { - val + 1 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn arithmetic_overflow_plus(val: i32) -> i32 { - val + 1 -} - - -// Arithmetic overflow minus ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_minus(val: i32) -> i32 { - val - 1 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn arithmetic_overflow_minus(val: i32) -> i32 { - val - 1 -} - - -// Arithmetic overflow mult ---------------------------------------------------- -#[cfg(cfail1)] -pub fn arithmetic_overflow_mult(val: i32) -> i32 { - val * 2 -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn arithmetic_overflow_mult(val: i32) -> i32 { - val * 2 -} - - -// Arithmetic overflow negation ------------------------------------------------ -#[cfg(cfail1)] -pub fn arithmetic_overflow_negation(val: i32) -> i32 { - -val -} - -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] -#[rustc_clean(cfg="cfail3")] -pub fn arithmetic_overflow_negation(val: i32) -> i32 { - -val -} diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index e729a2c039e..b9616d8c6b5 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index a16f4a2fdfd..3cdaf0e468a 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index d89d779c849..d7b70720418 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -23,7 +23,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index e09659be755..0816d6e5f45 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -23,7 +23,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index eb31175b6f2..a232883f7a9 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index 59346f5fdb2..c5521d2fae2 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -23,7 +23,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index ec4ae62b12b..85f6ef60c5d 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Z force-overflow-checks=off +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index eae5aea6510..d04ed03eb66 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -27,7 +27,7 @@ // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_body() { +pub fn change_loop_body() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -36,11 +36,9 @@ fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_body() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_body() { let mut _x = 0; while let Some(0u32) = None { _x = 2; @@ -52,7 +50,7 @@ fn change_loop_body() { // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_condition() { +pub fn change_loop_condition() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -61,11 +59,9 @@ fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_condition() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_condition() { let mut _x = 0; while let Some(1u32) = None { _x = 1; @@ -77,7 +73,7 @@ fn change_loop_condition() { // Add break ------------------------------------------------------------------- #[cfg(cfail1)] -fn add_break() { +pub fn add_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -85,11 +81,9 @@ fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn add_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -101,7 +95,7 @@ fn add_break() { // Add loop label -------------------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label() { +pub fn add_loop_label() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -110,11 +104,9 @@ fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; @@ -126,7 +118,7 @@ fn add_loop_label() { // Add loop label to break ----------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_break() { +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; @@ -135,11 +127,9 @@ fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; @@ -151,7 +141,7 @@ fn add_loop_label_to_break() { // Change break label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_break_label() { +pub fn change_break_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { 'inner: while let Some(0u32) = None { @@ -162,11 +152,9 @@ fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_break_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_break_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { 'inner: while let Some(0u32) = None { @@ -180,7 +168,7 @@ fn change_break_label() { // Add loop label to continue -------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_continue() { +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; @@ -189,11 +177,9 @@ fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_continue() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; @@ -205,7 +191,7 @@ fn add_loop_label_to_continue() { // Change continue label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_continue_label() { +pub fn change_continue_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { 'inner: while let Some(0u32) = None { @@ -216,11 +202,9 @@ fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { 'inner: while let Some(0u32) = None { @@ -234,7 +218,7 @@ fn change_continue_label() { // Change continue to break ---------------------------------------------------- #[cfg(cfail1)] -fn change_continue_to_break() { +pub fn change_continue_to_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; @@ -243,11 +227,9 @@ fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_to_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 6b1898e401b..7f2bbebde80 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -18,7 +18,7 @@ // must-compile-successfully // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph +// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -27,7 +27,7 @@ // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_body() { +pub fn change_loop_body() { let mut _x = 0; while true { _x = 1; @@ -36,11 +36,9 @@ fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_body() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_body() { let mut _x = 0; while true { _x = 2; @@ -52,7 +50,7 @@ fn change_loop_body() { // Change loop body ------------------------------------------------------------ #[cfg(cfail1)] -fn change_loop_condition() { +pub fn change_loop_condition() { let mut _x = 0; while true { _x = 1; @@ -61,11 +59,9 @@ fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_loop_condition() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_loop_condition() { let mut _x = 0; while false { _x = 1; @@ -77,7 +73,7 @@ fn change_loop_condition() { // Add break ------------------------------------------------------------------- #[cfg(cfail1)] -fn add_break() { +pub fn add_break() { let mut _x = 0; while true { _x = 1; @@ -85,11 +81,9 @@ fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")] +#[rustc_clean(cfg="cfail3")] +pub fn add_break() { let mut _x = 0; while true { _x = 1; @@ -101,7 +95,7 @@ fn add_break() { // Add loop label -------------------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label() { +pub fn add_loop_label() { let mut _x = 0; while true { _x = 1; @@ -110,11 +104,9 @@ fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label() { let mut _x = 0; 'label: while true { _x = 1; @@ -126,7 +118,7 @@ fn add_loop_label() { // Add loop label to break ----------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_break() { +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while true { _x = 1; @@ -135,11 +127,9 @@ fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while true { _x = 1; @@ -151,7 +141,7 @@ fn add_loop_label_to_break() { // Change break label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_break_label() { +pub fn change_break_label() { let mut _x = 0; 'outer: while true { 'inner: while true { @@ -162,11 +152,9 @@ fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_break_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_break_label() { let mut _x = 0; 'outer: while true { 'inner: while true { @@ -180,7 +168,7 @@ fn change_break_label() { // Add loop label to continue -------------------------------------------------- #[cfg(cfail1)] -fn add_loop_label_to_continue() { +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while true { _x = 1; @@ -189,11 +177,9 @@ fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn add_loop_label_to_continue() { +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] +pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while true { _x = 1; @@ -205,7 +191,7 @@ fn add_loop_label_to_continue() { // Change continue label ---------------------------------------------------------- #[cfg(cfail1)] -fn change_continue_label() { +pub fn change_continue_label() { let mut _x = 0; 'outer: while true { 'inner: while true { @@ -216,11 +202,9 @@ fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_label() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_label() { let mut _x = 0; 'outer: while true { 'inner: while true { @@ -234,7 +218,7 @@ fn change_continue_label() { // Change continue to break ---------------------------------------------------- #[cfg(cfail1)] -fn change_continue_to_break() { +pub fn change_continue_to_break() { let mut _x = 0; while true { _x = 1; @@ -243,11 +227,9 @@ fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -fn change_continue_to_break() { +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")] +#[rustc_clean(cfg="cfail3")] +pub fn change_continue_to_break() { let mut _x = 0; while true { _x = 1; diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs index 7f4e2b0f176..996c9ed21cf 100644 --- a/src/test/incremental/ich_method_call_trait_scope.rs +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -30,21 +30,10 @@ trait Trait2 { impl Trait2 for () { } -#[cfg(rpass1)] mod mod3 { + #[cfg(rpass1)] use Trait1; - - fn bar() { - ().method(); - } - - fn baz() { - 22; // no method call, traits in scope don't matter - } -} - -#[cfg(rpass2)] -mod mod3 { + #[cfg(rpass2)] use Trait2; #[rustc_clean(label="Hir", cfg="rpass2")] diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index 2e0f0ba0837..8566a24c84b 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -17,23 +17,18 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[cfg(cfail1)] -pub fn foo() { - pub fn bar() { } - pub fn baz() { } -} - -#[cfg(cfail2)] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_dirty(label="HirBody", cfg="cfail2")] pub fn foo() { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail2")] + #[cfg(cfail1)] pub fn baz() { } // order is different... #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="HirBody", cfg="cfail2")] pub fn bar() { } // but that doesn't matter. + #[cfg(cfail2)] + pub fn baz() { } // order is different... + pub fn bap() { } // neither does adding a new item } diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 49a88c530ff..9e5b51f3e7a 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -25,49 +25,29 @@ mod mod2 { pub struct Foo(pub i64); } -#[cfg(rpass1)] mod mod3 { - use test; + #[cfg(rpass1)] use mod1::Foo; - - fn in_expr() { - Foo(0); - } - - fn in_type() { - test::<Foo>(); - } -} - -#[cfg(rpass2)] -mod mod3 { - use mod1::Foo; // <-- Nothing changed, but reordered! use test; - #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] - fn in_expr() { - Foo(0); - } + // In rpass2 we move the use declaration. + #[cfg(rpass2)] + use mod1::Foo; + + // In rpass3 we let the declaration point to something else. + #[cfg(rpass3)] + use mod2::Foo; #[rustc_clean(label="Hir", cfg="rpass2")] #[rustc_clean(label="HirBody", cfg="rpass2")] - fn in_type() { - test::<Foo>(); - } -} - -#[cfg(rpass3)] -mod mod3 { - use test; - use mod2::Foo; // <-- This changed! - #[rustc_clean(label="Hir", cfg="rpass3")] #[rustc_dirty(label="HirBody", cfg="rpass3")] fn in_expr() { Foo(0); } + #[rustc_clean(label="Hir", cfg="rpass2")] + #[rustc_clean(label="HirBody", cfg="rpass2")] #[rustc_clean(label="Hir", cfg="rpass3")] #[rustc_dirty(label="HirBody", cfg="rpass3")] fn in_type() { diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs index 36d1b3ecbcd..3f669ae3fc8 100644 --- a/src/test/incremental/source_loc_macros.rs +++ b/src/test/incremental/source_loc_macros.rs @@ -35,28 +35,30 @@ fn file_same() { let _ = file!(); } -#[cfg(rpass1)] -fn line_different() { - let _ = line!(); -} - -#[cfg(rpass2)] #[rustc_clean(label="Hir", cfg="rpass2")] #[rustc_dirty(label="HirBody", cfg="rpass2")] fn line_different() { - let _ = line!(); -} - -#[cfg(rpass1)] -fn col_different() { - let _ = column!(); + #[cfg(rpass1)] + { + let _ = line!(); + } + #[cfg(rpass2)] + { + let _ = line!(); + } } -#[cfg(rpass2)] #[rustc_clean(label="Hir", cfg="rpass2")] #[rustc_dirty(label="HirBody", cfg="rpass2")] fn col_different() { - let _ = column!(); + #[cfg(rpass1)] + { + let _ = column!(); + } + #[cfg(rpass2)] + { + let _ = column!(); + } } fn main() { diff --git a/src/test/incremental/spans_insignificant_w_o_debuginfo.rs b/src/test/incremental/spans_insignificant_w_o_debuginfo.rs deleted file mode 100644 index 90ec4a9d558..00000000000 --- a/src/test/incremental/spans_insignificant_w_o_debuginfo.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test makes sure that just changing a definition's location in the -// source file does *not* change its incr. comp. hash, if debuginfo is disabled. - -// revisions:rpass1 rpass2 - -// compile-flags: -Z query-dep-graph - -#![feature(rustc_attrs)] - -#[cfg(rpass1)] -pub fn main() {} - -#[cfg(rpass2)] -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] -pub fn main() {} diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index c0bf35e781c..1fefec7a0a7 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -23,8 +23,7 @@ pub fn main() { } #[cfg(rpass2)] -#[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_dirty(label="MirOptimized", cfg="rpass2")] pub fn main() { let _ = 0u8 + 1; } diff --git a/src/test/mir-opt/nll/liveness-call-subtlety.rs b/src/test/mir-opt/nll/liveness-call-subtlety.rs index e4dd99f5a1e..09288cf69ff 100644 --- a/src/test/mir-opt/nll/liveness-call-subtlety.rs +++ b/src/test/mir-opt/nll/liveness-call-subtlety.rs @@ -28,18 +28,18 @@ fn main() { // START rustc.main.nll.0.mir // | Live variables on entry to bb0: [] // bb0: { -// | Live variables at bb0[0]: [] +// | Live variables on entry to bb0[0]: [] // StorageLive(_1); -// | Live variables at bb0[1]: [] +// | Live variables on entry to bb0[1]: [] // _1 = const <std::boxed::Box<T>>::new(const 22usize) -> [return: bb2, unwind: bb1]; // } // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // | Live variables on entry to bb2: [_1 (drop)] // bb2: { -// | Live variables at bb2[0]: [_1 (drop)] +// | Live variables on entry to bb2[0]: [_1 (drop)] // StorageLive(_2); -// | Live variables at bb2[1]: [_1 (drop)] +// | Live variables on entry to bb2[1]: [_1 (drop)] // _2 = const can_panic() -> [return: bb3, unwind: bb4]; // } // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/liveness-drop-intra-block.rs b/src/test/mir-opt/nll/liveness-drop-intra-block.rs index 8dae7738067..b060222a95f 100644 --- a/src/test/mir-opt/nll/liveness-drop-intra-block.rs +++ b/src/test/mir-opt/nll/liveness-drop-intra-block.rs @@ -27,15 +27,15 @@ fn main() { // START rustc.main.nll.0.mir // | Live variables on entry to bb2: [] // bb2: { -// | Live variables at bb2[0]: [] +// | Live variables on entry to bb2[0]: [] // _1 = const 55usize; -// | Live variables at bb2[1]: [_1] +// | Live variables on entry to bb2[1]: [_1] // StorageLive(_3); -// | Live variables at bb2[2]: [_1] +// | Live variables on entry to bb2[2]: [_1] // StorageLive(_4); -// | Live variables at bb2[3]: [_1] +// | Live variables on entry to bb2[3]: [_1] // _4 = _1; -// | Live variables at bb2[4]: [_4] +// | Live variables on entry to bb2[4]: [_4] // _3 = const use_x(move _4) -> [return: bb3, unwind: bb1]; // } // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/liveness-interblock.rs b/src/test/mir-opt/nll/liveness-interblock.rs index 5d799d3d90b..671f5e5292a 100644 --- a/src/test/mir-opt/nll/liveness-interblock.rs +++ b/src/test/mir-opt/nll/liveness-interblock.rs @@ -31,18 +31,18 @@ fn main() { // START rustc.main.nll.0.mir // | Live variables on entry to bb3: [_1] // bb3: { -// | Live variables at bb3[0]: [_1] +// | Live variables on entry to bb3[0]: [_1] // StorageLive(_4); -// | Live variables at bb3[1]: [_1] +// | Live variables on entry to bb3[1]: [_1] // _4 = _1; -// | Live variables at bb3[2]: [_4] +// | Live variables on entry to bb3[2]: [_4] // _3 = const make_live(move _4) -> [return: bb5, unwind: bb1]; // } // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // | Live variables on entry to bb4: [] // bb4: { -// | Live variables at bb4[0]: [] +// | Live variables on entry to bb4[0]: [] // _5 = const make_dead() -> [return: bb6, unwind: bb1]; // } // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs index 7039de727fa..0c42585a528 100644 --- a/src/test/mir-opt/nll/named-lifetimes-basic.rs +++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs @@ -26,9 +26,18 @@ fn main() { // END RUST SOURCE // START rustc.use_x.nll.0.mir -// | '_#0r: {bb0[0], bb0[1], '_#0r} -// | '_#1r: {bb0[0], bb0[1], '_#1r} -// | '_#2r: {bb0[0], bb0[1], '_#2r} -// | '_#3r: {bb0[0], bb0[1], '_#3r} +// | Free Region Mapping +// | '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#3r] +// | '_#1r | External | ['_#1r] +// | '_#2r | External | ['_#2r, '_#1r] +// | '_#3r | Local | ['_#3r] +// | +// | Inferred Region Values +// | '_#0r | {bb0[0], bb0[1], '_#0r} +// | '_#1r | {bb0[0], bb0[1], '_#1r} +// | '_#2r | {bb0[0], bb0[1], '_#2r} +// | '_#3r | {bb0[0], bb0[1], '_#3r} +// | +// ... // fn use_x(_1: &'_#1r mut i32, _2: &'_#2r u32, _3: &'_#1r u32, _4: &'_#3r u32) -> bool { // END rustc.use_x.nll.0.mir diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs index f51e839e4fc..d203472f20c 100644 --- a/src/test/mir-opt/nll/reborrow-basic.rs +++ b/src/test/mir-opt/nll/reborrow-basic.rs @@ -28,11 +28,10 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#6r: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]} +// | '_#6r | {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]} +// ... +// | '_#8r | {bb0[11], bb0[12], bb0[13], bb0[14]} // ... -// | '_#8r: {bb0[11], bb0[12], bb0[13], bb0[14]} -// END rustc.main.nll.0.mir -// START rustc.main.nll.0.mir // let _2: &'_#6r mut i32; // ... // let _4: &'_#8r mut i32; diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs index cfbc51f9e18..c04cedbc04b 100644 --- a/src/test/mir-opt/nll/region-liveness-basic.rs +++ b/src/test/mir-opt/nll/region-liveness-basic.rs @@ -31,26 +31,26 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]} -// | '_#2r: {bb2[1], bb3[0], bb3[1]} +// | '_#1r | {bb2[0], bb2[1], bb3[0], bb3[1]} +// | '_#2r | {bb2[1], bb3[0], bb3[1]} // ... // let _2: &'_#2r usize; // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // bb2: { -// | Live variables at bb2[0]: [_1, _3] +// | Live variables on entry to bb2[0]: [_1, _3] // _2 = &'_#1r _1[_3]; -// | Live variables at bb2[1]: [_2] +// | Live variables on entry to bb2[1]: [_2] // switchInt(const true) -> [0u8: bb4, otherwise: bb3]; // } // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // bb3: { -// | Live variables at bb3[0]: [_2] +// | Live variables on entry to bb3[0]: [_2] // StorageLive(_7); -// | Live variables at bb3[1]: [_2] +// | Live variables on entry to bb3[1]: [_2] // _7 = (*_2); -// | Live variables at bb3[2]: [_7] +// | Live variables on entry to bb3[2]: [_7] // _6 = const use_x(move _7) -> [return: bb5, unwind: bb1]; // } // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs index 04a30dc284d..e2ad49a4436 100644 --- a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs +++ b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs @@ -44,5 +44,5 @@ unsafe impl<#[may_dangle] T> Drop for Wrap<T> { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]} +// | '_#5r | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]} // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs index 5569fe7f574..e0272a51d03 100644 --- a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs +++ b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs @@ -46,5 +46,5 @@ impl<T> Drop for Wrap<T> { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]} +// | '_#5r | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]} // END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs index 679f31fdab9..8aa0eb1a3a9 100644 --- a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs +++ b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs @@ -36,10 +36,10 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]} +// | '_#1r | {bb2[0], bb2[1], bb3[0], bb3[1]} // ... -// | '_#3r: {bb8[1], bb8[2], bb8[3], bb8[4]} -// | '_#4r: {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]} +// | '_#3r | {bb8[1], bb8[2], bb8[3], bb8[4]} +// | '_#4r | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]} // ... // let mut _2: &'_#4r usize; // ... diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs index 471d77aefac..2bc165bd3c4 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic.rs +++ b/src/test/mir-opt/nll/region-subtyping-basic.rs @@ -32,9 +32,9 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#1r: {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]} -// | '_#2r: {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]} -// | '_#3r: {bb2[5], bb2[6], bb3[0], bb3[1]} +// | '_#1r | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]} +// | '_#2r | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]} +// | '_#3r | {bb2[5], bb2[6], bb3[0], bb3[1]} // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // let _2: &'_#2r usize; diff --git a/src/test/parse-fail/issue-17383.rs b/src/test/parse-fail/issue-17383.rs index 1b33cb38857..48f629fd828 100644 --- a/src/test/parse-fail/issue-17383.rs +++ b/src/test/parse-fail/issue-17383.rs @@ -12,7 +12,7 @@ enum X { A = - b'a' //~ ERROR discriminator values can only be used with a c-like enum + b'a' //~ ERROR discriminator values can only be used with a field-less enum , B(isize) } diff --git a/src/test/parse-fail/tag-variant-disr-non-nullary.rs b/src/test/parse-fail/tag-variant-disr-non-nullary.rs index f90b1cc94bb..2d86589285c 100644 --- a/src/test/parse-fail/tag-variant-disr-non-nullary.rs +++ b/src/test/parse-fail/tag-variant-disr-non-nullary.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -//error-pattern: discriminator values can only be used with a c-like enum +//error-pattern: discriminator values can only be used with a field-less enum enum color { red = 0xff0000, diff --git a/src/test/run-pass/abi-sysv64-arg-passing.rs b/src/test/run-pass/abi-sysv64-arg-passing.rs index 23dd0603184..4ec3f16f7af 100644 --- a/src/test/run-pass/abi-sysv64-arg-passing.rs +++ b/src/test/run-pass/abi-sysv64-arg-passing.rs @@ -39,7 +39,6 @@ // note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows -#![feature(abi_sysv64)] #[allow(dead_code)] #[allow(improper_ctypes)] diff --git a/src/test/run-pass/abi-sysv64-register-usage.rs b/src/test/run-pass/abi-sysv64-register-usage.rs index 7e3b32122ac..1cae8671266 100644 --- a/src/test/run-pass/abi-sysv64-register-usage.rs +++ b/src/test/run-pass/abi-sysv64-register-usage.rs @@ -15,7 +15,6 @@ // ignore-arm // ignore-aarch64 -#![feature(abi_sysv64)] #![feature(asm)] #[cfg(target_arch = "x86_64")] diff --git a/src/test/run-pass/auxiliary/svh-a-comment.rs b/src/test/run-pass/auxiliary/svh-a-comment.rs deleted file mode 100644 index 22e40822eec..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-comment.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -pub fn foo<T:U>(_: isize) -> isize { - // a comment does not affect the svh - 3 -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/auxiliary/svh-a-doc.rs b/src/test/run-pass/auxiliary/svh-a-doc.rs deleted file mode 100644 index 3d8a728967a..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-doc.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -// Adding some documentation does not affect the svh. - -/// foo always returns three. -pub fn foo<T:U>(_: isize) -> isize { - 3 -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/auxiliary/svh-a-macro.rs b/src/test/run-pass/auxiliary/svh-a-macro.rs deleted file mode 100644 index 41d7eb7b186..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-macro.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -pub fn foo<T:U>(_: isize) -> isize { - // a macro invocation in a function body does not affect the svh, - // as long as it yields the same code. - three!() -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/auxiliary/svh-a-no-change.rs b/src/test/run-pass/auxiliary/svh-a-no-change.rs deleted file mode 100644 index 31a97f695f0..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-no-change.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -pub fn foo<T:U>(_: isize) -> isize { - 3 -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs b/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs deleted file mode 100644 index e405c337abe..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -// cfg attribute does not affect the svh, as long as it yields the same code. -#[cfg(not(an_unused_name))] -pub fn foo<T:U>(_: isize) -> isize { - 3 -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/auxiliary/svh-a-whitespace.rs b/src/test/run-pass/auxiliary/svh-a-whitespace.rs deleted file mode 100644 index 9ef788c9842..00000000000 --- a/src/test/run-pass/auxiliary/svh-a-whitespace.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 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. - -//! The `svh-a-*.rs` files are all deviations from the base file -//! svh-a-base.rs with some difference (usually in `fn foo`) that -//! should not affect the strict version hash (SVH) computation -//! (#14132). - -#![crate_name = "a"] - -macro_rules! three { - () => { 3 } -} - -pub trait U {} -pub trait V {} -impl U for () {} -impl V for () {} - -static A_CONSTANT : isize = 2; - -pub fn foo<T:U>(_: isize) -> isize { - - 3 - -} - -pub fn an_unused_name() -> isize { - 4 -} diff --git a/src/test/run-pass/hygiene/issue-44128.rs b/src/test/run-pass/hygiene/issue-44128.rs new file mode 100644 index 00000000000..213ee1edff4 --- /dev/null +++ b/src/test/run-pass/hygiene/issue-44128.rs @@ -0,0 +1,25 @@ +// 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. + +#![feature(decl_macro)] + +pub macro create_struct($a:ident) { + struct $a; + impl Clone for $a { + fn clone(&self) -> Self { + $a + } + } +} + +fn main() { + create_struct!(Test); + Test.clone(); +} diff --git a/src/test/run-pass/issue-44373.rs b/src/test/run-pass/issue-44373.rs index 06627e2ad93..d0f8ed96f4c 100644 --- a/src/test/run-pass/issue-44373.rs +++ b/src/test/run-pass/issue-44373.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z borrowck=compare + struct Foo(bool); struct Container(&'static [&'static Foo]); diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs index bda90d3aaec..9592da77a1b 100644 --- a/src/test/run-pass/match-pipe-binding.rs +++ b/src/test/run-pass/match-pipe-binding.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z borrowck=compare fn test1() { // from issue 6338 diff --git a/src/test/run-pass/svh-add-doc.rs b/src/test/run-pass/svh-add-doc.rs deleted file mode 100644 index ea07ebe3646..00000000000 --- a/src/test/run-pass/svh-add-doc.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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. - -// note that these aux-build directives must be in this order -// aux-build:svh-a-base.rs -// aux-build:svh-b.rs -// aux-build:svh-a-doc.rs - -// pretty-expanded FIXME #23616 - -extern crate a; -extern crate b; - -fn main() { - b::foo() -} diff --git a/src/test/run-pass/svh-add-macro.rs b/src/test/run-pass/svh-add-macro.rs deleted file mode 100644 index 4e0192c40c2..00000000000 --- a/src/test/run-pass/svh-add-macro.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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. - -// note that these aux-build directives must be in this order -// aux-build:svh-a-base.rs -// aux-build:svh-b.rs -// aux-build:svh-a-macro.rs - -// pretty-expanded FIXME #23616 - -extern crate a; -extern crate b; - -fn main() { - b::foo() -} diff --git a/src/test/run-pass/svh-add-nothing.rs b/src/test/run-pass/svh-add-nothing.rs index 9aa56ed2a76..aca50859b6e 100644 --- a/src/test/run-pass/svh-add-nothing.rs +++ b/src/test/run-pass/svh-add-nothing.rs @@ -11,7 +11,7 @@ // note that these aux-build directives must be in this order // aux-build:svh-a-base.rs // aux-build:svh-b.rs -// aux-build:svh-a-no-change.rs +// aux-build:svh-a-base.rs // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/svh-add-redundant-cfg.rs b/src/test/run-pass/svh-add-redundant-cfg.rs deleted file mode 100644 index 2da3004aaf1..00000000000 --- a/src/test/run-pass/svh-add-redundant-cfg.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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. - -// note that these aux-build directives must be in this order -// aux-build:svh-a-base.rs -// aux-build:svh-b.rs -// aux-build:svh-a-redundant-cfg.rs - -// pretty-expanded FIXME #23616 - -extern crate a; -extern crate b; - -fn main() { - b::foo() -} diff --git a/src/test/run-pass/svh-add-whitespace.rs b/src/test/run-pass/svh-add-whitespace.rs deleted file mode 100644 index bfc676bde26..00000000000 --- a/src/test/run-pass/svh-add-whitespace.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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. - -// note that these aux-build directives must be in this order -// aux-build:svh-a-base.rs -// aux-build:svh-b.rs -// aux-build:svh-a-whitespace.rs - -// pretty-expanded FIXME #23616 - -extern crate a; -extern crate b; - -fn main() { - b::foo() -} diff --git a/src/test/run-pass/svh-add-comment.rs b/src/test/run-pass/thinlto/weak-works.rs index 4d7b61e08f5..b9719e04f34 100644 --- a/src/test/run-pass/svh-add-comment.rs +++ b/src/test/run-pass/thinlto/weak-works.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,16 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// note that these aux-build directives must be in this order -// aux-build:svh-a-base.rs -// aux-build:svh-b.rs -// aux-build:svh-a-comment.rs +// compile-flags: -C codegen-units=8 -Z thinlto +// ignore-windows +// min-llvm-version 4.0 -// pretty-expanded FIXME #23616 +#![feature(linkage)] -extern crate a; -extern crate b; +pub mod foo { + #[linkage = "weak"] + #[no_mangle] + pub extern "C" fn FOO() -> i32 { + 0 + } +} + +mod bar { + extern "C" { + fn FOO() -> i32; + } + + pub fn bar() -> i32 { + unsafe { FOO() } + } +} fn main() { - b::foo() + bar::bar(); } diff --git a/src/test/compile-fail/auxiliary/cfg-target-thread-local.rs b/src/test/ui/auxiliary/cfg-target-thread-local.rs index d1971a5e1ae..d1971a5e1ae 100644 --- a/src/test/compile-fail/auxiliary/cfg-target-thread-local.rs +++ b/src/test/ui/auxiliary/cfg-target-thread-local.rs diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr index 41ab60f017f..e95078f2547 100644 --- a/src/test/ui/codemap_tests/tab.stderr +++ b/src/test/ui/codemap_tests/tab.stderr @@ -1,16 +1,16 @@ error[E0425]: cannot find value `bar` in this scope --> $DIR/tab.rs:14:2 | -14 | bar; //~ ERROR cannot find value `bar` - | ^^^ not found in this scope +14 | bar; //~ ERROR cannot find value `bar` + | ^^^ not found in this scope error[E0308]: mismatched types --> $DIR/tab.rs:18:2 | 17 | fn foo() { | - help: try adding a return type: `-> &'static str ` -18 | "bar boo" //~ ERROR mismatched types - | ^^^^^^^^^^^ expected (), found reference +18 | "bar boo" //~ ERROR mismatched types + | ^^^^^^^^^^^^^^^^^^^^ expected (), found reference | = note: expected type `()` found type `&'static str` diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr index 7f6b55e7eb8..34c49d97562 100644 --- a/src/test/ui/codemap_tests/tab_2.stderr +++ b/src/test/ui/codemap_tests/tab_2.stderr @@ -1,8 +1,8 @@ error: unterminated double quote string --> $DIR/tab_2.rs:14:7 | -14 | """; //~ ERROR unterminated double quote - | _______^ +14 | """; //~ ERROR unterminated double quote + | ___________________^ 15 | | } | |__^ diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr index 278e590a36d..32202062663 100644 --- a/src/test/ui/codemap_tests/tab_3.stderr +++ b/src/test/ui/codemap_tests/tab_3.stderr @@ -1,11 +1,11 @@ error[E0382]: use of moved value: `some_vec` --> $DIR/tab_3.rs:17:20 | -15 | some_vec.into_iter(); - | -------- value moved here -16 | { -17 | println!("{:?}", some_vec); //~ ERROR use of moved - | ^^^^^^^^ value used here after move +15 | some_vec.into_iter(); + | -------- value moved here +16 | { +17 | println!("{:?}", some_vec); //~ ERROR use of moved + | ^^^^^^^^ value used here after move | = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait diff --git a/src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs b/src/test/ui/feature-gate-abi-msp430-interrupt.rs index 030e37475c0..030e37475c0 100644 --- a/src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs +++ b/src/test/ui/feature-gate-abi-msp430-interrupt.rs diff --git a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr new file mode 100644 index 00000000000..b05be6e4391 --- /dev/null +++ b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr @@ -0,0 +1,10 @@ +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi-msp430-interrupt.rs:14:1 + | +14 | extern "msp430-interrupt" fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/ui/feature-gate-abi.rs index 45c715f51fe..45c715f51fe 100644 --- a/src/test/compile-fail/feature-gate-abi.rs +++ b/src/test/ui/feature-gate-abi.rs diff --git a/src/test/ui/feature-gate-abi.stderr b/src/test/ui/feature-gate-abi.stderr new file mode 100644 index 00000000000..7d2ad0be391 --- /dev/null +++ b/src/test/ui/feature-gate-abi.stderr @@ -0,0 +1,450 @@ +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:19:1 + | +19 | extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:20:1 + | +20 | extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:21:1 + | +21 | extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:22:1 + | +22 | extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:23:1 + | +23 | extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:24:1 + | +24 | extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:25:1 + | +25 | extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:26:1 + | +26 | extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:30:5 + | +30 | extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:31:5 + | +31 | extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:32:5 + | +32 | extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:33:5 + | +33 | extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:34:5 + | +34 | extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:35:5 + | +35 | extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:36:5 + | +36 | extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:37:5 + | +37 | extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:39:5 + | +39 | extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:40:5 + | +40 | extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:41:5 + | +41 | extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:42:5 + | +42 | extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:43:5 + | +43 | extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:44:5 + | +44 | extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:45:5 + | +45 | extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:46:5 + | +46 | extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:53:5 + | +53 | extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:54:5 + | +54 | extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:55:5 + | +55 | extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:56:5 + | +56 | extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:57:5 + | +57 | extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:58:5 + | +58 | extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:59:5 + | +59 | extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:60:5 + | +60 | extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:65:5 + | +65 | extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:66:5 + | +66 | extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:67:5 + | +67 | extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:68:5 + | +68 | extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:69:5 + | +69 | extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:70:5 + | +70 | extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:71:5 + | +71 | extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:72:5 + | +72 | extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:76:11 + | +76 | type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:77:11 + | +77 | type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:78:11 + | +78 | type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:79:11 + | +79 | type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:80:11 + | +80 | type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:81:11 + | +81 | type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:82:11 + | +82 | type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:83:11 + | +83 | type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:86:1 + | +86 | extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: platform intrinsics are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-abi.rs:87:1 + | +87 | extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(platform_intrinsics)] to the crate attributes to enable + +error: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:88:1 + | +88 | extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_vectorcall)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-abi.rs:89:1 + | +89 | extern "rust-call" {} //~ ERROR rust-call ABI is subject to change + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: msp430-interrupt ABI is experimental and subject to change (see issue #38487) + --> $DIR/feature-gate-abi.rs:90:1 + | +90 | extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable + +error: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi.rs:91:1 + | +91 | extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_ptx)] to the crate attributes to enable + +error: x86-interrupt ABI is experimental and subject to change (see issue #40180) + --> $DIR/feature-gate-abi.rs:92:1 + | +92 | extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable + +error: thiscall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:93:1 + | +93 | extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(abi_thiscall)] to the crate attributes to enable + +error: aborting due to 56 previous errors + diff --git a/src/test/compile-fail/unadjusted-unstable.rs b/src/test/ui/feature-gate-abi_unadjusted.rs index 2c23050085d..501f4451ed8 100644 --- a/src/test/compile-fail/unadjusted-unstable.rs +++ b/src/test/ui/feature-gate-abi_unadjusted.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-abi_unadjusted - extern "unadjusted" fn foo() { //~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable } diff --git a/src/test/ui/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gate-abi_unadjusted.stderr new file mode 100644 index 00000000000..3cc43847156 --- /dev/null +++ b/src/test/ui/feature-gate-abi_unadjusted.stderr @@ -0,0 +1,12 @@ +error: unadjusted ABI is an implementation detail and perma-unstable + --> $DIR/feature-gate-abi_unadjusted.rs:11:1 + | +11 | / extern "unadjusted" fn foo() { +12 | | //~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable +13 | | } + | |_^ + | + = help: add #![feature(abi_unadjusted)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-advanced-slice-features.rs b/src/test/ui/feature-gate-advanced-slice-features.rs index dc9b4e634ab..dc9b4e634ab 100644 --- a/src/test/compile-fail/feature-gate-advanced-slice-features.rs +++ b/src/test/ui/feature-gate-advanced-slice-features.rs diff --git a/src/test/ui/feature-gate-advanced-slice-features.stderr b/src/test/ui/feature-gate-advanced-slice-features.stderr new file mode 100644 index 00000000000..815593d07a5 --- /dev/null +++ b/src/test/ui/feature-gate-advanced-slice-features.stderr @@ -0,0 +1,18 @@ +error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121) + --> $DIR/feature-gate-advanced-slice-features.rs:18:9 + | +18 | [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable + +error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121) + --> $DIR/feature-gate-advanced-slice-features.rs:19:9 + | +19 | [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-allocator_internals.rs b/src/test/ui/feature-gate-allocator_internals.rs index b519a985ec5..b519a985ec5 100644 --- a/src/test/compile-fail/feature-gate-allocator_internals.rs +++ b/src/test/ui/feature-gate-allocator_internals.rs diff --git a/src/test/ui/feature-gate-allocator_internals.stderr b/src/test/ui/feature-gate-allocator_internals.stderr new file mode 100644 index 00000000000..f1f4705b3bb --- /dev/null +++ b/src/test/ui/feature-gate-allocator_internals.stderr @@ -0,0 +1,10 @@ +error: the `#[default_lib_allocator]` attribute is an experimental feature + --> $DIR/feature-gate-allocator_internals.rs:11:1 + | +11 | #![default_lib_allocator] //~ ERROR: attribute is an experimental feature + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(allocator_internals)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-allow-internal-unsafe-nested-macro.rs b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.rs index 590dc619f2f..590dc619f2f 100644 --- a/src/test/compile-fail/feature-gate-allow-internal-unsafe-nested-macro.rs +++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.rs diff --git a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr new file mode 100644 index 00000000000..40bdde37ee8 --- /dev/null +++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -0,0 +1,13 @@ +error: allow_internal_unsafe side-steps the unsafe_code lint + --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:18:9 + | +18 | #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +25 | bar!(); + | ------- in this macro invocation + | + = help: add #![feature(allow_internal_unsafe)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.rs index 9af501b1419..9af501b1419 100644 --- a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs +++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.rs diff --git a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr new file mode 100644 index 00000000000..60d72fbc3b3 --- /dev/null +++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -0,0 +1,13 @@ +error: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:18:9 + | +18 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +25 | bar!(); + | ------- in this macro invocation + | + = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-struct.rs b/src/test/ui/feature-gate-allow-internal-unstable-struct.rs index b186278ef8b..b186278ef8b 100644 --- a/src/test/compile-fail/feature-gate-allow-internal-unstable-struct.rs +++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.rs diff --git a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr new file mode 100644 index 00000000000..2fb86ce8f4e --- /dev/null +++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr @@ -0,0 +1,10 @@ +error: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable-struct.rs:14:1 + | +14 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable.rs b/src/test/ui/feature-gate-allow-internal-unstable.rs index 61a362cb37f..61a362cb37f 100644 --- a/src/test/compile-fail/feature-gate-allow-internal-unstable.rs +++ b/src/test/ui/feature-gate-allow-internal-unstable.rs diff --git a/src/test/ui/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gate-allow-internal-unstable.stderr new file mode 100644 index 00000000000..a5740a1a789 --- /dev/null +++ b/src/test/ui/feature-gate-allow-internal-unstable.stderr @@ -0,0 +1,10 @@ +error: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable.rs:13:1 + | +13 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/ui/feature-gate-allow_fail.rs index 11247402809..11247402809 100644 --- a/src/test/compile-fail/feature-gate-allow_fail.rs +++ b/src/test/ui/feature-gate-allow_fail.rs diff --git a/src/test/ui/feature-gate-allow_fail.stderr b/src/test/ui/feature-gate-allow_fail.stderr new file mode 100644 index 00000000000..65cd137459a --- /dev/null +++ b/src/test/ui/feature-gate-allow_fail.stderr @@ -0,0 +1,10 @@ +error: allow_fail attribute is currently unstable (see issue #42219) + --> $DIR/feature-gate-allow_fail.rs:13:1 + | +13 | #[allow_fail] //~ ERROR allow_fail attribute is currently unstable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(allow_fail)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs b/src/test/ui/feature-gate-arbitrary-self-types.rs index ff0306f1993..ff0306f1993 100644 --- a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs +++ b/src/test/ui/feature-gate-arbitrary-self-types.rs diff --git a/src/test/ui/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gate-arbitrary-self-types.stderr new file mode 100644 index 00000000000..2ef517cc9e1 --- /dev/null +++ b/src/test/ui/feature-gate-arbitrary-self-types.stderr @@ -0,0 +1,29 @@ +error: arbitrary `self` types are unstable (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:14:18 + | +14 | fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>` + +error: arbitrary `self` types are unstable (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:20:18 + | +20 | fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>` + +error: arbitrary `self` types are unstable (see issue #44874) + --> $DIR/feature-gate-arbitrary-self-types.rs:24:18 + | +24 | fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>` + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/asm-gated.rs b/src/test/ui/feature-gate-asm.rs index cd9cc223701..8d053bdae78 100644 --- a/src/test/compile-fail/asm-gated.rs +++ b/src/test/ui/feature-gate-asm.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-asm - fn main() { unsafe { asm!(""); //~ ERROR inline assembly is not stable enough diff --git a/src/test/ui/feature-gate-asm.stderr b/src/test/ui/feature-gate-asm.stderr new file mode 100644 index 00000000000..ff68a4fb23e --- /dev/null +++ b/src/test/ui/feature-gate-asm.stderr @@ -0,0 +1,10 @@ +error: inline assembly is not stable enough for use and is subject to change (see issue #29722) + --> $DIR/feature-gate-asm.rs:13:9 + | +13 | asm!(""); //~ ERROR inline assembly is not stable enough + | ^^^^^^^^^ + | + = help: add #![feature(asm)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/asm-gated2.rs b/src/test/ui/feature-gate-asm2.rs index 222190de9fe..222190de9fe 100644 --- a/src/test/compile-fail/asm-gated2.rs +++ b/src/test/ui/feature-gate-asm2.rs diff --git a/src/test/ui/feature-gate-asm2.stderr b/src/test/ui/feature-gate-asm2.stderr new file mode 100644 index 00000000000..1e02cede61d --- /dev/null +++ b/src/test/ui/feature-gate-asm2.stderr @@ -0,0 +1,10 @@ +error: inline assembly is not stable enough for use and is subject to change (see issue #29722) + --> $DIR/feature-gate-asm2.rs:15:24 + | +15 | println!("{}", asm!("")); //~ ERROR inline assembly is not stable + | ^^^^^^^^ + | + = help: add #![feature(asm)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs b/src/test/ui/feature-gate-assoc-type-defaults.rs index de3521eb0f2..de3521eb0f2 100644 --- a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs +++ b/src/test/ui/feature-gate-assoc-type-defaults.rs diff --git a/src/test/ui/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gate-assoc-type-defaults.stderr new file mode 100644 index 00000000000..5e288469168 --- /dev/null +++ b/src/test/ui/feature-gate-assoc-type-defaults.stderr @@ -0,0 +1,10 @@ +error: associated type defaults are unstable (see issue #29661) + --> $DIR/feature-gate-assoc-type-defaults.rs:14:5 + | +14 | type Bar = u8; //~ ERROR associated type defaults are unstable + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(associated_type_defaults)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-box-expr.rs b/src/test/ui/feature-gate-box-expr.rs index 65d437d0c0d..65d437d0c0d 100644 --- a/src/test/compile-fail/feature-gate-box-expr.rs +++ b/src/test/ui/feature-gate-box-expr.rs diff --git a/src/test/ui/feature-gate-box-expr.stderr b/src/test/ui/feature-gate-box-expr.stderr new file mode 100644 index 00000000000..cef5adbd15a --- /dev/null +++ b/src/test/ui/feature-gate-box-expr.stderr @@ -0,0 +1,10 @@ +error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779) + --> $DIR/feature-gate-box-expr.rs:22:13 + | +22 | let x = box 'c'; //~ ERROR box expression syntax is experimental + | ^^^^^^^ + | + = help: add #![feature(box_syntax)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-box-pat.rs b/src/test/ui/feature-gate-box_patterns.rs index c30f3952dbf..e64081823e7 100644 --- a/src/test/compile-fail/feature-gate-box-pat.rs +++ b/src/test/ui/feature-gate-box_patterns.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-box_patterns - fn main() { let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental println!("x: {}", x); diff --git a/src/test/ui/feature-gate-box_patterns.stderr b/src/test/ui/feature-gate-box_patterns.stderr new file mode 100644 index 00000000000..0a30de58a1f --- /dev/null +++ b/src/test/ui/feature-gate-box_patterns.stderr @@ -0,0 +1,10 @@ +error: box pattern syntax is experimental (see issue #29641) + --> $DIR/feature-gate-box_patterns.rs:12:9 + | +12 | let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental + | ^^^^^ + | + = help: add #![feature(box_patterns)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/ui/feature-gate-box_syntax.rs index 9a68ddb3059..a2643fe02b8 100644 --- a/src/test/compile-fail/gated-box-syntax.rs +++ b/src/test/ui/feature-gate-box_syntax.rs @@ -10,8 +10,6 @@ // Test that the use of the box syntax is gated by `box_syntax` feature gate. -// gate-test-box_syntax - fn main() { let x = box 3; //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead. diff --git a/src/test/ui/feature-gate-box_syntax.stderr b/src/test/ui/feature-gate-box_syntax.stderr new file mode 100644 index 00000000000..9b21dd03051 --- /dev/null +++ b/src/test/ui/feature-gate-box_syntax.stderr @@ -0,0 +1,10 @@ +error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779) + --> $DIR/feature-gate-box_syntax.rs:14:13 + | +14 | let x = box 3; + | ^^^^^ + | + = help: add #![feature(box_syntax)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-catch_expr.rs b/src/test/ui/feature-gate-catch_expr.rs index 5568a5cf0aa..5568a5cf0aa 100644 --- a/src/test/compile-fail/feature-gate-catch_expr.rs +++ b/src/test/ui/feature-gate-catch_expr.rs diff --git a/src/test/ui/feature-gate-catch_expr.stderr b/src/test/ui/feature-gate-catch_expr.stderr new file mode 100644 index 00000000000..f486373d225 --- /dev/null +++ b/src/test/ui/feature-gate-catch_expr.stderr @@ -0,0 +1,14 @@ +error: `catch` expression is experimental (see issue #31436) + --> $DIR/feature-gate-catch_expr.rs:12:24 + | +12 | let catch_result = do catch { //~ ERROR `catch` expression is experimental + | ________________________^ +13 | | let x = 5; +14 | | x +15 | | }; + | |_____^ + | + = help: add #![feature(catch_expr)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-cfg-target-feature.rs b/src/test/ui/feature-gate-cfg-target-feature.rs index 7832e1c7c51..7832e1c7c51 100644 --- a/src/test/compile-fail/feature-gate-cfg-target-feature.rs +++ b/src/test/ui/feature-gate-cfg-target-feature.rs diff --git a/src/test/ui/feature-gate-cfg-target-feature.stderr b/src/test/ui/feature-gate-cfg-target-feature.stderr new file mode 100644 index 00000000000..60dc6fbb57e --- /dev/null +++ b/src/test/ui/feature-gate-cfg-target-feature.stderr @@ -0,0 +1,34 @@ +error: `cfg(target_feature)` is experimental and subject to change (see issue #29717) + --> $DIR/feature-gate-cfg-target-feature.rs:12:12 + | +12 | #[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_feature)] to the crate attributes to enable + +error: `cfg(target_feature)` is experimental and subject to change (see issue #29717) + --> $DIR/feature-gate-cfg-target-feature.rs:11:7 + | +11 | #[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_feature)] to the crate attributes to enable + +error: `cfg(target_feature)` is experimental and subject to change (see issue #29717) + --> $DIR/feature-gate-cfg-target-feature.rs:15:19 + | +15 | #[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_feature)] to the crate attributes to enable + +error: `cfg(target_feature)` is experimental and subject to change (see issue #29717) + --> $DIR/feature-gate-cfg-target-feature.rs:19:10 + | +19 | cfg!(target_feature = "x"); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_feature)] to the crate attributes to enable + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gate-cfg-target-has-atomic.rs index aa27f8922c0..aa27f8922c0 100644 --- a/src/test/compile-fail/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gate-cfg-target-has-atomic.rs diff --git a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr new file mode 100644 index 00000000000..5daf5de7123 --- /dev/null +++ b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr @@ -0,0 +1,122 @@ +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:23:7 + | +23 | #[cfg(target_has_atomic = "8")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7 + | +29 | #[cfg(target_has_atomic = "8")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7 + | +34 | #[cfg(target_has_atomic = "16")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7 + | +39 | #[cfg(target_has_atomic = "16")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7 + | +44 | #[cfg(target_has_atomic = "32")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7 + | +49 | #[cfg(target_has_atomic = "32")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7 + | +54 | #[cfg(target_has_atomic = "64")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7 + | +59 | #[cfg(target_has_atomic = "64")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7 + | +64 | #[cfg(target_has_atomic = "ptr")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7 + | +69 | #[cfg(target_has_atomic = "ptr")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:76:10 + | +76 | cfg!(target_has_atomic = "8"); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10 + | +78 | cfg!(target_has_atomic = "16"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10 + | +80 | cfg!(target_has_atomic = "32"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10 + | +82 | cfg!(target_has_atomic = "64"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) + --> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10 + | +84 | cfg!(target_has_atomic = "ptr"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable + +error: aborting due to 15 previous errors + diff --git a/src/test/compile-fail/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gate-cfg-target-thread-local.rs index 985bd8320e0..985bd8320e0 100644 --- a/src/test/compile-fail/feature-gate-cfg-target-thread-local.rs +++ b/src/test/ui/feature-gate-cfg-target-thread-local.rs diff --git a/src/test/ui/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gate-cfg-target-thread-local.stderr new file mode 100644 index 00000000000..9e2eea6e0a4 --- /dev/null +++ b/src/test/ui/feature-gate-cfg-target-thread-local.stderr @@ -0,0 +1,10 @@ +error: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594) + --> $DIR/feature-gate-cfg-target-thread-local.rs:19:16 + | +19 | #[cfg_attr(target_thread_local, thread_local)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_thread_local)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-cfg-target-vendor.rs b/src/test/ui/feature-gate-cfg-target-vendor.rs index e68a84d3553..e68a84d3553 100644 --- a/src/test/compile-fail/feature-gate-cfg-target-vendor.rs +++ b/src/test/ui/feature-gate-cfg-target-vendor.rs diff --git a/src/test/ui/feature-gate-cfg-target-vendor.stderr b/src/test/ui/feature-gate-cfg-target-vendor.stderr new file mode 100644 index 00000000000..c5709600dba --- /dev/null +++ b/src/test/ui/feature-gate-cfg-target-vendor.stderr @@ -0,0 +1,34 @@ +error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718) + --> $DIR/feature-gate-cfg-target-vendor.rs:12:12 + | +12 | #[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable + +error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718) + --> $DIR/feature-gate-cfg-target-vendor.rs:11:7 + | +11 | #[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable + +error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718) + --> $DIR/feature-gate-cfg-target-vendor.rs:15:19 + | +15 | #[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable + +error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718) + --> $DIR/feature-gate-cfg-target-vendor.rs:19:10 + | +19 | cfg!(target_vendor = "x"); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/feature-gate-clone-closures.rs b/src/test/ui/feature-gate-clone-closures.rs index a15153ea7bf..a15153ea7bf 100644 --- a/src/test/compile-fail/feature-gate-clone-closures.rs +++ b/src/test/ui/feature-gate-clone-closures.rs diff --git a/src/test/ui/feature-gate-clone-closures.stderr b/src/test/ui/feature-gate-clone-closures.stderr new file mode 100644 index 00000000000..3e07aa17440 --- /dev/null +++ b/src/test/ui/feature-gate-clone-closures.stderr @@ -0,0 +1,10 @@ +error[E0599]: no method named `clone` found for type `[closure@$DIR/feature-gate-clone-closures.rs:16:17: 18:6 a:_]` in the current scope + --> $DIR/feature-gate-clone-closures.rs:20:23 + | +20 | let hello = hello.clone(); //~ ERROR no method named `clone` found for type + | ^^^^^ + | + = note: hello is a function, perhaps you wish to call it + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-compiler-builtins.rs b/src/test/ui/feature-gate-compiler-builtins.rs index f9334f1d3b0..f9334f1d3b0 100644 --- a/src/test/compile-fail/feature-gate-compiler-builtins.rs +++ b/src/test/ui/feature-gate-compiler-builtins.rs diff --git a/src/test/ui/feature-gate-compiler-builtins.stderr b/src/test/ui/feature-gate-compiler-builtins.stderr new file mode 100644 index 00000000000..ebf42b2bdd8 --- /dev/null +++ b/src/test/ui/feature-gate-compiler-builtins.stderr @@ -0,0 +1,10 @@ +error: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable + --> $DIR/feature-gate-compiler-builtins.rs:11:1 + | +11 | #![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(compiler_builtins)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/concat_idents-gate.rs b/src/test/ui/feature-gate-concat_idents.rs index 5b125d0e51c..f4d97445725 100644 --- a/src/test/compile-fail/concat_idents-gate.rs +++ b/src/test/ui/feature-gate-concat_idents.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-concat_idents - const XY_1: i32 = 10; fn main() { diff --git a/src/test/ui/feature-gate-concat_idents.stderr b/src/test/ui/feature-gate-concat_idents.stderr new file mode 100644 index 00000000000..c980668c298 --- /dev/null +++ b/src/test/ui/feature-gate-concat_idents.stderr @@ -0,0 +1,18 @@ +error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599) + --> $DIR/feature-gate-concat_idents.rs:15:13 + | +15 | let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(concat_idents)] to the crate attributes to enable + +error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599) + --> $DIR/feature-gate-concat_idents.rs:16:13 + | +16 | let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(concat_idents)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/gated-concat_idents.rs b/src/test/ui/feature-gate-concat_idents2.rs index af288a97904..af288a97904 100644 --- a/src/test/compile-fail/gated-concat_idents.rs +++ b/src/test/ui/feature-gate-concat_idents2.rs diff --git a/src/test/ui/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gate-concat_idents2.stderr new file mode 100644 index 00000000000..9cfd954eec8 --- /dev/null +++ b/src/test/ui/feature-gate-concat_idents2.stderr @@ -0,0 +1,10 @@ +error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599) + --> $DIR/feature-gate-concat_idents2.rs:14:5 + | +14 | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(concat_idents)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/concat_idents-gate2.rs b/src/test/ui/feature-gate-concat_idents3.rs index 5a9ffe98c93..5a9ffe98c93 100644 --- a/src/test/compile-fail/concat_idents-gate2.rs +++ b/src/test/ui/feature-gate-concat_idents3.rs diff --git a/src/test/ui/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gate-concat_idents3.stderr new file mode 100644 index 00000000000..8399ca3c501 --- /dev/null +++ b/src/test/ui/feature-gate-concat_idents3.stderr @@ -0,0 +1,18 @@ +error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599) + --> $DIR/feature-gate-concat_idents3.rs:17:20 + | +17 | assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(concat_idents)] to the crate attributes to enable + +error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599) + --> $DIR/feature-gate-concat_idents3.rs:18:20 + | +18 | assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(concat_idents)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/impl-trait/feature-gate.rs b/src/test/ui/feature-gate-conservative_impl_trait.rs index d46a16450db..7a3ae639bfc 100644 --- a/src/test/compile-fail/impl-trait/feature-gate.rs +++ b/src/test/ui/feature-gate-conservative_impl_trait.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-conservative_impl_trait - fn foo() -> impl Fn() { || {} } //~^ ERROR `impl Trait` in return position is experimental diff --git a/src/test/ui/feature-gate-conservative_impl_trait.stderr b/src/test/ui/feature-gate-conservative_impl_trait.stderr new file mode 100644 index 00000000000..72a4f52926a --- /dev/null +++ b/src/test/ui/feature-gate-conservative_impl_trait.stderr @@ -0,0 +1,10 @@ +error: `impl Trait` in return position is experimental (see issue #34511) + --> $DIR/feature-gate-conservative_impl_trait.rs:11:13 + | +11 | fn foo() -> impl Fn() { || {} } + | ^^^^^^^^^ + | + = help: add #![feature(conservative_impl_trait)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-const-indexing.rs b/src/test/ui/feature-gate-const-indexing.rs index 0d61878cd80..0d61878cd80 100644 --- a/src/test/compile-fail/feature-gate-const-indexing.rs +++ b/src/test/ui/feature-gate-const-indexing.rs diff --git a/src/test/ui/feature-gate-const-indexing.stderr b/src/test/ui/feature-gate-const-indexing.stderr new file mode 100644 index 00000000000..bc4b687800d --- /dev/null +++ b/src/test/ui/feature-gate-const-indexing.stderr @@ -0,0 +1,8 @@ +error[E0080]: constant evaluation error + --> $DIR/feature-gate-const-indexing.rs:16:24 + | +16 | const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; //~ ERROR constant evaluation error + | ^^^^^^ the index operation on const values is unstable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/const-fn-stability.rs b/src/test/ui/feature-gate-const_fn.rs index d093364497a..1d1dedddaaa 100644 --- a/src/test/compile-fail/const-fn-stability.rs +++ b/src/test/ui/feature-gate-const_fn.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-const_fn - // Test use of const fn without feature gate. const fn foo() -> usize { 0 } //~ ERROR const fn is unstable diff --git a/src/test/ui/feature-gate-const_fn.stderr b/src/test/ui/feature-gate-const_fn.stderr new file mode 100644 index 00000000000..c62229ac71b --- /dev/null +++ b/src/test/ui/feature-gate-const_fn.stderr @@ -0,0 +1,60 @@ +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-const_fn.rs:16:5 + | +16 | const fn foo() -> u32; //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-const_fn.rs:18:5 + | +18 | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error[E0379]: trait fns cannot be declared const + --> $DIR/feature-gate-const_fn.rs:27:5 + | +27 | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^ trait fns cannot be const + +error: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-const_fn.rs:13:1 + | +13 | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-const_fn.rs:16:5 + | +16 | const fn foo() -> u32; //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-const_fn.rs:18:5 + | +18 | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-const_fn.rs:23:5 + | +23 | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error: const fn is unstable (see issue #24111) + --> $DIR/feature-gate-const_fn.rs:27:5 + | +27 | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_fn)] to the crate attributes to enable + +error: aborting due to 8 previous errors + diff --git a/src/test/compile-fail/feature-gate-copy-closures.rs b/src/test/ui/feature-gate-copy-closures.rs index b11b09eb9fd..b11b09eb9fd 100644 --- a/src/test/compile-fail/feature-gate-copy-closures.rs +++ b/src/test/ui/feature-gate-copy-closures.rs diff --git a/src/test/ui/feature-gate-copy-closures.stderr b/src/test/ui/feature-gate-copy-closures.stderr new file mode 100644 index 00000000000..9b324672f22 --- /dev/null +++ b/src/test/ui/feature-gate-copy-closures.stderr @@ -0,0 +1,12 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/feature-gate-copy-closures.rs:18:9 + | +17 | let b = hello; + | - value moved here +18 | let c = hello; //~ ERROR use of moved value: `hello` [E0382] + | ^ value used here after move + | + = note: move occurs because `hello` has type `[closure@$DIR/feature-gate-copy-closures.rs:13:17: 15:6 a:&i32]`, which does not implement the `Copy` trait + +error: aborting due to previous error + diff --git a/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs b/src/test/ui/feature-gate-crate_in_paths.rs index 830ec5959b7..830ec5959b7 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs +++ b/src/test/ui/feature-gate-crate_in_paths.rs diff --git a/src/test/ui/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gate-crate_in_paths.stderr new file mode 100644 index 00000000000..b13c82ecfc9 --- /dev/null +++ b/src/test/ui/feature-gate-crate_in_paths.stderr @@ -0,0 +1,10 @@ +error: `crate` in paths is experimental (see issue #45477) + --> $DIR/feature-gate-crate_in_paths.rs:14:15 + | +14 | let _ = ::crate::S; //~ ERROR `crate` in paths is experimental + | ^^^^^ + | + = help: add #![feature(crate_in_paths)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs b/src/test/ui/feature-gate-crate_visibility_modifier.rs index a2937d6de31..a2937d6de31 100644 --- a/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs +++ b/src/test/ui/feature-gate-crate_visibility_modifier.rs diff --git a/src/test/ui/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gate-crate_visibility_modifier.stderr new file mode 100644 index 00000000000..0862744b87b --- /dev/null +++ b/src/test/ui/feature-gate-crate_visibility_modifier.stderr @@ -0,0 +1,10 @@ +error: `crate` visibility modifier is experimental (see issue #45388) + --> $DIR/feature-gate-crate_visibility_modifier.rs:11:1 + | +11 | crate struct Bender { //~ ERROR `crate` visibility modifier is experimental + | ^^^^^ + | + = help: add #![feature(crate_visibility_modifier)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/attr-literals.rs b/src/test/ui/feature-gate-custom_attribute.rs index e77fde845ae..b5428803517 100644 --- a/src/test/compile-fail/attr-literals.rs +++ b/src/test/ui/feature-gate-custom_attribute.rs @@ -10,8 +10,6 @@ // Check that literals in attributes parse just fine. -// gate-test-custom_attribute - #![feature(rustc_attrs, attr_literals)] #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gate-custom_attribute.stderr new file mode 100644 index 00000000000..866ebfe8f2f --- /dev/null +++ b/src/test/ui/feature-gate-custom_attribute.stderr @@ -0,0 +1,106 @@ +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:17:1 + | +17 | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:18:1 + | +18 | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:19:1 + | +19 | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:20:1 + | +20 | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:21:1 + | +21 | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:22:1 + | +22 | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:23:1 + | +23 | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:24:1 + | +24 | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:25:1 + | +25 | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:26:1 + | +26 | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:27:1 + | +27 | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:28:1 + | +28 | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute.rs:29:1 + | +29 | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 13 previous errors + diff --git a/src/test/compile-fail/attr-on-generic-formals-are-visited.rs b/src/test/ui/feature-gate-custom_attribute2.rs index 0d89c52d885..0d89c52d885 100644 --- a/src/test/compile-fail/attr-on-generic-formals-are-visited.rs +++ b/src/test/ui/feature-gate-custom_attribute2.rs diff --git a/src/test/ui/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gate-custom_attribute2.stderr new file mode 100644 index 00000000000..3e4ea58a7a3 --- /dev/null +++ b/src/test/ui/feature-gate-custom_attribute2.stderr @@ -0,0 +1,138 @@ +error: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:23:13 + | +23 | struct StLt<#[lt_struct] 'a>(&'a u32); + | ^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:25:13 + | +25 | struct StTy<#[ty_struct] I>(I); + | ^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:28:11 + | +28 | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:30:11 + | +30 | enum EnTy<#[ty_enum] J> { A(J), B } + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:33:12 + | +33 | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } + | ^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:35:12 + | +35 | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } + | ^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:38:11 + | +38 | type TyLt<#[lt_type] 'd> = &'d u32; + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:40:11 + | +40 | type TyTy<#[ty_type] L> = (L, ); + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:43:6 + | +43 | impl<#[lt_inherent] 'e> StLt<'e> { } + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:45:6 + | +45 | impl<#[ty_inherent] M> StTy<M> { } + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:48:6 + | +48 | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:52:6 + | +52 | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> { + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:57:9 + | +57 | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } + | ^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:59:9 + | +59 | fn f_ty<#[ty_fn] O>(_: O) { } + | ^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:63:13 + | +63 | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:65:13 + | +65 | fn m_ty<#[ty_meth] P>(_: P) { } + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/feature-gate-custom_attribute2.rs:70:19 + | +70 | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 + | ^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 17 previous errors + diff --git a/src/test/compile-fail/single-derive-attr.rs b/src/test/ui/feature-gate-custom_derive.rs index cd37611aced..0b1b3141f5b 100644 --- a/src/test/compile-fail/single-derive-attr.rs +++ b/src/test/ui/feature-gate-custom_derive.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-custom_derive - #[derive_Clone] //~^ ERROR attributes of the form `#[derive_*]` are reserved struct Test; diff --git a/src/test/ui/feature-gate-custom_derive.stderr b/src/test/ui/feature-gate-custom_derive.stderr new file mode 100644 index 00000000000..e806c808631 --- /dev/null +++ b/src/test/ui/feature-gate-custom_derive.stderr @@ -0,0 +1,10 @@ +error: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) + --> $DIR/feature-gate-custom_derive.rs:11:1 + | +11 | #[derive_Clone] + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_derive)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-decl_macro.rs b/src/test/ui/feature-gate-decl_macro.rs index c5c83977c77..c5c83977c77 100644 --- a/src/test/compile-fail/feature-gate-decl_macro.rs +++ b/src/test/ui/feature-gate-decl_macro.rs diff --git a/src/test/ui/feature-gate-decl_macro.stderr b/src/test/ui/feature-gate-decl_macro.stderr new file mode 100644 index 00000000000..49ce4eb10b6 --- /dev/null +++ b/src/test/ui/feature-gate-decl_macro.stderr @@ -0,0 +1,10 @@ +error: `macro` is experimental (see issue #39412) + --> $DIR/feature-gate-decl_macro.rs:13:1 + | +13 | macro m() {} //~ ERROR `macro` is experimental (see issue #39412) + | ^^^^^^^^^^^^ + | + = help: add #![feature(decl_macro)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/ui/feature-gate-default_type_parameter_fallback.rs index f424cbf0c32..ccc5ec49f13 100644 --- a/src/test/compile-fail/type-parameter-invalid-lint.rs +++ b/src/test/ui/feature-gate-default_type_parameter_fallback.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-default_type_parameter_fallback - #![allow(unused)] fn avg<T=i32>(_: T) {} diff --git a/src/test/ui/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gate-default_type_parameter_fallback.stderr new file mode 100644 index 00000000000..d756a69e8c1 --- /dev/null +++ b/src/test/ui/feature-gate-default_type_parameter_fallback.stderr @@ -0,0 +1,21 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. + --> $DIR/feature-gate-default_type_parameter_fallback.rs:13:8 + | +13 | fn avg<T=i32>(_: T) {} + | ^ + | + = note: #[deny(invalid_type_param_default)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887> + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. + --> $DIR/feature-gate-default_type_parameter_fallback.rs:18:6 + | +18 | impl<T=i32> S<T> {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887> + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-doc_cfg.rs b/src/test/ui/feature-gate-doc_cfg.rs index 1a77d918014..1a77d918014 100644 --- a/src/test/compile-fail/feature-gate-doc_cfg.rs +++ b/src/test/ui/feature-gate-doc_cfg.rs diff --git a/src/test/ui/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gate-doc_cfg.stderr new file mode 100644 index 00000000000..c2d8a934ab8 --- /dev/null +++ b/src/test/ui/feature-gate-doc_cfg.stderr @@ -0,0 +1,10 @@ +error: #[doc(cfg(...))] is experimental (see issue #43781) + --> $DIR/feature-gate-doc_cfg.rs:11:1 + | +11 | #[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(doc_cfg)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-doc_masked.rs b/src/test/ui/feature-gate-doc_masked.rs index bb5be9d6971..bb5be9d6971 100644 --- a/src/test/compile-fail/feature-gate-doc_masked.rs +++ b/src/test/ui/feature-gate-doc_masked.rs diff --git a/src/test/ui/feature-gate-doc_masked.stderr b/src/test/ui/feature-gate-doc_masked.stderr new file mode 100644 index 00000000000..11020765304 --- /dev/null +++ b/src/test/ui/feature-gate-doc_masked.stderr @@ -0,0 +1,10 @@ +error: #[doc(masked)] is experimental (see issue #44027) + --> $DIR/feature-gate-doc_masked.rs:11:1 + | +11 | #[doc(masked)] //~ ERROR: #[doc(masked)] is experimental + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(doc_masked)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gate-doc_spotlight.rs index 6369358538d..6369358538d 100644 --- a/src/test/compile-fail/feature-gate-doc_spotlight.rs +++ b/src/test/ui/feature-gate-doc_spotlight.rs diff --git a/src/test/ui/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gate-doc_spotlight.stderr new file mode 100644 index 00000000000..b743a1e94bc --- /dev/null +++ b/src/test/ui/feature-gate-doc_spotlight.stderr @@ -0,0 +1,10 @@ +error: #[doc(spotlight)] is experimental (see issue #45040) + --> $DIR/feature-gate-doc_spotlight.rs:11:1 + | +11 | #[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(doc_spotlight)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs b/src/test/ui/feature-gate-dotdoteq_in_patterns.rs index 1fb139bf07f..1fb139bf07f 100644 --- a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs +++ b/src/test/ui/feature-gate-dotdoteq_in_patterns.rs diff --git a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr new file mode 100644 index 00000000000..5319dcef2d5 --- /dev/null +++ b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr @@ -0,0 +1,10 @@ +error: `..=` syntax in patterns is experimental (see issue #28237) + --> $DIR/feature-gate-dotdoteq_in_patterns.rs:13:9 + | +13 | 0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental + | ^^^^^^^ + | + = help: add #![feature(dotdoteq_in_patterns)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs b/src/test/ui/feature-gate-dropck-ugeh-2.rs index 70ec561439c..70ec561439c 100644 --- a/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs +++ b/src/test/ui/feature-gate-dropck-ugeh-2.rs diff --git a/src/test/ui/feature-gate-dropck-ugeh-2.stderr b/src/test/ui/feature-gate-dropck-ugeh-2.stderr new file mode 100644 index 00000000000..0555b485d4c --- /dev/null +++ b/src/test/ui/feature-gate-dropck-ugeh-2.stderr @@ -0,0 +1,14 @@ +error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761 + --> $DIR/feature-gate-dropck-ugeh-2.rs:17:5 + | +17 | #[unsafe_destructor_blind_to_params] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: lint level defined here + --> $DIR/feature-gate-dropck-ugeh-2.rs:11:9 + | +11 | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/ui/feature-gate-dropck-ugeh.rs index 360895d30b0..360895d30b0 100644 --- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs +++ b/src/test/ui/feature-gate-dropck-ugeh.rs diff --git a/src/test/ui/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gate-dropck-ugeh.stderr new file mode 100644 index 00000000000..b030ebcd881 --- /dev/null +++ b/src/test/ui/feature-gate-dropck-ugeh.stderr @@ -0,0 +1,10 @@ +error: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498) + --> $DIR/feature-gate-dropck-ugeh.rs:29:5 + | +29 | #[unsafe_destructor_blind_to_params] // This is the UGEH attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(dropck_parametricity)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-dyn-trait.rs b/src/test/ui/feature-gate-dyn-trait.rs index 4b3803d019b..4b3803d019b 100644 --- a/src/test/compile-fail/feature-gate-dyn-trait.rs +++ b/src/test/ui/feature-gate-dyn-trait.rs diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr new file mode 100644 index 00000000000..28ecfdf1131 --- /dev/null +++ b/src/test/ui/feature-gate-dyn-trait.stderr @@ -0,0 +1,10 @@ +error: `dyn Trait` syntax is unstable (see issue #44662) + --> $DIR/feature-gate-dyn-trait.rs:12:14 + | +12 | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable + | ^^^^^^^^^ + | + = help: add #![feature(dyn_trait)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-exclusive-range-pattern.rs b/src/test/ui/feature-gate-exclusive-range-pattern.rs index e0b6d5986ff..e0b6d5986ff 100644 --- a/src/test/compile-fail/feature-gate-exclusive-range-pattern.rs +++ b/src/test/ui/feature-gate-exclusive-range-pattern.rs diff --git a/src/test/ui/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gate-exclusive-range-pattern.stderr new file mode 100644 index 00000000000..c6785d6f29d --- /dev/null +++ b/src/test/ui/feature-gate-exclusive-range-pattern.stderr @@ -0,0 +1,10 @@ +error: exclusive range pattern syntax is experimental (see issue #37854) + --> $DIR/feature-gate-exclusive-range-pattern.rs:13:9 + | +13 | 0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental + | ^^^^^^ + | + = help: add #![feature(exclusive_range_pattern)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-extern_types.rs b/src/test/ui/feature-gate-extern_types.rs index 1203b598df3..1203b598df3 100644 --- a/src/test/compile-fail/feature-gate-extern_types.rs +++ b/src/test/ui/feature-gate-extern_types.rs diff --git a/src/test/ui/feature-gate-extern_types.stderr b/src/test/ui/feature-gate-extern_types.stderr new file mode 100644 index 00000000000..3815862e899 --- /dev/null +++ b/src/test/ui/feature-gate-extern_types.stderr @@ -0,0 +1,10 @@ +error: extern types are experimental (see issue #43467) + --> $DIR/feature-gate-extern_types.rs:12:5 + | +12 | type T; //~ ERROR extern types are experimental + | ^^^^^^^ + | + = help: add #![feature(extern_types)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-external_doc.rs b/src/test/ui/feature-gate-external_doc.rs index fa0a2a29078..fa0a2a29078 100644 --- a/src/test/compile-fail/feature-gate-external_doc.rs +++ b/src/test/ui/feature-gate-external_doc.rs diff --git a/src/test/ui/feature-gate-external_doc.stderr b/src/test/ui/feature-gate-external_doc.stderr new file mode 100644 index 00000000000..5479ab8bc91 --- /dev/null +++ b/src/test/ui/feature-gate-external_doc.stderr @@ -0,0 +1,10 @@ +error: #[doc(include = "...")] is experimental (see issue #44732) + --> $DIR/feature-gate-external_doc.rs:11:1 + | +11 | #[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(external_doc)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-feature-gate.rs b/src/test/ui/feature-gate-feature-gate.rs index b903b29658b..b903b29658b 100644 --- a/src/test/compile-fail/feature-gate-feature-gate.rs +++ b/src/test/ui/feature-gate-feature-gate.rs diff --git a/src/test/ui/feature-gate-feature-gate.stderr b/src/test/ui/feature-gate-feature-gate.stderr new file mode 100644 index 00000000000..3d5f0d70bb2 --- /dev/null +++ b/src/test/ui/feature-gate-feature-gate.stderr @@ -0,0 +1,14 @@ +error: unstable feature + --> $DIR/feature-gate-feature-gate.rs:12:12 + | +12 | #![feature(intrinsics)] //~ ERROR unstable feature + | ^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/feature-gate-feature-gate.rs:11:11 + | +11 | #![forbid(unstable_features)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-fn_must_use-cap-lints-allow.rs b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs index 1c04199c05f..1c04199c05f 100644 --- a/src/test/compile-fail/feature-gate-fn_must_use-cap-lints-allow.rs +++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr new file mode 100644 index 00000000000..9b16e9be68a --- /dev/null +++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr @@ -0,0 +1,6 @@ +error: compilation successful + --> $DIR/feature-gate-fn_must_use-cap-lints-allow.rs:22:1 + | +22 | fn main() {} //~ ERROR compilation successful + | ^^^^^^^^^^^^ + diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/ui/feature-gate-fn_must_use.rs index 72fdcc76cf4..72fdcc76cf4 100644 --- a/src/test/compile-fail/feature-gate-fn_must_use.rs +++ b/src/test/ui/feature-gate-fn_must_use.rs diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr new file mode 100644 index 00000000000..ed4953d27b8 --- /dev/null +++ b/src/test/ui/feature-gate-fn_must_use.stderr @@ -0,0 +1,22 @@ +warning: `#[must_use]` on methods is experimental (see issue #43302) + --> $DIR/feature-gate-fn_must_use.rs:16:5 + | +16 | #[must_use] //~ WARN `#[must_use]` on methods is experimental + | ^^^^^^^^^^^ + | + = help: add #![feature(fn_must_use)] to the crate attributes to enable + +warning: `#[must_use]` on functions is experimental (see issue #43302) + --> $DIR/feature-gate-fn_must_use.rs:20:1 + | +20 | #[must_use] //~ WARN `#[must_use]` on functions is experimental + | ^^^^^^^^^^^ + | + = help: add #![feature(fn_must_use)] to the crate attributes to enable + +error: compilation successful + --> $DIR/feature-gate-fn_must_use.rs:31:1 + | +31 | fn main() {} //~ ERROR compilation successful + | ^^^^^^^^^^^^ + diff --git a/src/test/compile-fail/feature-gate-fundamental.rs b/src/test/ui/feature-gate-fundamental.rs index 18718a0d0be..18718a0d0be 100644 --- a/src/test/compile-fail/feature-gate-fundamental.rs +++ b/src/test/ui/feature-gate-fundamental.rs diff --git a/src/test/ui/feature-gate-fundamental.stderr b/src/test/ui/feature-gate-fundamental.stderr new file mode 100644 index 00000000000..0fc75ee30b9 --- /dev/null +++ b/src/test/ui/feature-gate-fundamental.stderr @@ -0,0 +1,10 @@ +error: the `#[fundamental]` attribute is an experimental feature (see issue #29635) + --> $DIR/feature-gate-fundamental.rs:11:1 + | +11 | #[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(fundamental)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-generators.rs b/src/test/ui/feature-gate-generators.rs index 3754f92d8cd..3754f92d8cd 100644 --- a/src/test/compile-fail/feature-gate-generators.rs +++ b/src/test/ui/feature-gate-generators.rs diff --git a/src/test/ui/feature-gate-generators.stderr b/src/test/ui/feature-gate-generators.stderr new file mode 100644 index 00000000000..82acb401338 --- /dev/null +++ b/src/test/ui/feature-gate-generators.stderr @@ -0,0 +1,10 @@ +error: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:12:5 + | +12 | yield true; //~ ERROR yield syntax is experimental + | ^^^^^^^^^^ + | + = help: add #![feature(generators)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gate-generic_associated_types.rs index 724ec2496f2..724ec2496f2 100644 --- a/src/test/compile-fail/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gate-generic_associated_types.rs diff --git a/src/test/ui/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gate-generic_associated_types.stderr new file mode 100644 index 00000000000..7b2507e1fb1 --- /dev/null +++ b/src/test/ui/feature-gate-generic_associated_types.stderr @@ -0,0 +1,34 @@ +error: generic associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:14:5 + | +14 | type Pointer<T>: Deref<Target = T>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + +error: generic associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:16:5 + | +16 | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + +error: generic associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:22:5 + | +22 | type Pointer<usize> = Box<usize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + +error: generic associated types are unstable (see issue #44265) + --> $DIR/feature-gate-generic_associated_types.rs:24:5 + | +24 | type Pointer2<u32> = Box<u32>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_associated_types)] to the crate attributes to enable + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs b/src/test/ui/feature-gate-generic_param_attrs.rs index b341f7c7825..944802f450a 100644 --- a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs +++ b/src/test/ui/feature-gate-generic_param_attrs.rs @@ -16,8 +16,6 @@ // using `rustc_attrs` feature. There is a separate compile-fail/ test // ensuring that the attribute feature-gating works in this context.) -// gate-test-generic_param_attrs - #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/feature-gate-generic_param_attrs.stderr b/src/test/ui/feature-gate-generic_param_attrs.stderr new file mode 100644 index 00000000000..da2e6403029 --- /dev/null +++ b/src/test/ui/feature-gate-generic_param_attrs.stderr @@ -0,0 +1,138 @@ +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:22:13 + | +22 | struct StLt<#[rustc_lt_struct] 'a>(&'a u32); + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:24:13 + | +24 | struct StTy<#[rustc_ty_struct] I>(I); + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:27:11 + | +27 | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B } + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:29:11 + | +29 | enum EnTy<#[rustc_ty_enum] J> { A(J), B } + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:32:12 + | +32 | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:34:12 + | +34 | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); } + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:37:11 + | +37 | type TyLt<#[rustc_lt_type] 'd> = &'d u32; + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:39:11 + | +39 | type TyTy<#[rustc_ty_type] L> = (L, ); + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:42:6 + | +42 | impl<#[rustc_lt_inherent] 'e> StLt<'e> { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:44:6 + | +44 | impl<#[rustc_ty_inherent] M> StTy<M> { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:47:6 + | +47 | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> { + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:51:6 + | +51 | impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> { + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:56:9 + | +56 | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:58:9 + | +58 | fn f_ty<#[rustc_ty_fn] O>(_: O) { } + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:62:13 + | +62 | fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on type parameter bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:64:13 + | +64 | fn m_ty<#[rustc_ty_meth] P>(_: P) { } + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: attributes on lifetime bindings are experimental (see issue #34761) + --> $DIR/feature-gate-generic_param_attrs.rs:69:19 + | +69 | where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(generic_param_attrs)] to the crate attributes to enable + +error: aborting due to 17 previous errors + diff --git a/src/test/compile-fail/feature-gate-global_allocator.rs b/src/test/ui/feature-gate-global_allocator.rs index ff3c342f9e0..ff3c342f9e0 100644 --- a/src/test/compile-fail/feature-gate-global_allocator.rs +++ b/src/test/ui/feature-gate-global_allocator.rs diff --git a/src/test/ui/feature-gate-global_allocator.stderr b/src/test/ui/feature-gate-global_allocator.stderr new file mode 100644 index 00000000000..7e6c4288ff3 --- /dev/null +++ b/src/test/ui/feature-gate-global_allocator.stderr @@ -0,0 +1,10 @@ +error: the `#[global_allocator]` attribute is an experimental feature + --> $DIR/feature-gate-global_allocator.rs:11:1 + | +11 | #[global_allocator] //~ ERROR: attribute is an experimental feature + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(global_allocator)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-global_asm.rs b/src/test/ui/feature-gate-global_asm.rs index 77f61ba47b0..77f61ba47b0 100644 --- a/src/test/compile-fail/feature-gate-global_asm.rs +++ b/src/test/ui/feature-gate-global_asm.rs diff --git a/src/test/ui/feature-gate-global_asm.stderr b/src/test/ui/feature-gate-global_asm.stderr new file mode 100644 index 00000000000..de0ba1a7b32 --- /dev/null +++ b/src/test/ui/feature-gate-global_asm.stderr @@ -0,0 +1,10 @@ +error: `global_asm!` is not stable enough for use and is subject to change (see issue #35119) + --> $DIR/feature-gate-global_asm.rs:11:1 + | +11 | global_asm!(""); //~ ERROR `global_asm!` is not stable + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(global_asm)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/i128-feature.rs b/src/test/ui/feature-gate-i128_type.rs index e94fd14a421..ddb49a3e5d9 100644 --- a/src/test/compile-fail/i128-feature.rs +++ b/src/test/ui/feature-gate-i128_type.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-i128_type - fn test2() { 0i128; //~ ERROR 128-bit integers are not stable } diff --git a/src/test/ui/feature-gate-i128_type.stderr b/src/test/ui/feature-gate-i128_type.stderr new file mode 100644 index 00000000000..df623cac49a --- /dev/null +++ b/src/test/ui/feature-gate-i128_type.stderr @@ -0,0 +1,18 @@ +error: 128-bit integers are not stable (see issue #35118) + --> $DIR/feature-gate-i128_type.rs:12:5 + | +12 | 0i128; //~ ERROR 128-bit integers are not stable + | ^^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error: 128-bit integers are not stable (see issue #35118) + --> $DIR/feature-gate-i128_type.rs:16:5 + | +16 | 0u128; //~ ERROR 128-bit integers are not stable + | ^^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/i128-feature-2.rs b/src/test/ui/feature-gate-i128_type2.rs index d3bd810ceb2..d3bd810ceb2 100644 --- a/src/test/compile-fail/i128-feature-2.rs +++ b/src/test/ui/feature-gate-i128_type2.rs diff --git a/src/test/ui/feature-gate-i128_type2.stderr b/src/test/ui/feature-gate-i128_type2.stderr new file mode 100644 index 00000000000..26653a5739b --- /dev/null +++ b/src/test/ui/feature-gate-i128_type2.stderr @@ -0,0 +1,46 @@ +error: 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-i128_type2.rs:13:15 + | +13 | fn test1() -> i128 { //~ ERROR 128-bit type is unstable + | ^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error: 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-i128_type2.rs:17:17 + | +17 | fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable + | ^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error: 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-i128_type2.rs:22:12 + | +22 | let x: i128 = 0; //~ ERROR 128-bit type is unstable + | ^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error: 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-i128_type2.rs:26:12 + | +26 | let x: u128 = 0; //~ ERROR 128-bit type is unstable + | ^^^^ + | + = help: add #![feature(i128_type)] to the crate attributes to enable + +error[E0601]: main function not found + +error: repr with 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-i128_type2.rs:30:1 + | +30 | / enum A { //~ ERROR 128-bit type is unstable +31 | | A(u64) +32 | | } + | |_^ + | + = help: add #![feature(repr128)] to the crate attributes to enable + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/feature-gate-in_band_lifetimes.rs b/src/test/ui/feature-gate-in_band_lifetimes.rs index ae1f81c2f57..ae1f81c2f57 100644 --- a/src/test/compile-fail/feature-gate-in_band_lifetimes.rs +++ b/src/test/ui/feature-gate-in_band_lifetimes.rs diff --git a/src/test/ui/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gate-in_band_lifetimes.stderr new file mode 100644 index 00000000000..3b03ef2dd33 --- /dev/null +++ b/src/test/ui/feature-gate-in_band_lifetimes.stderr @@ -0,0 +1,104 @@ +error[E0261]: use of undeclared lifetime name `'x` + --> $DIR/feature-gate-in_band_lifetimes.rs:13:12 + | +13 | fn foo(x: &'x u8) -> &'x u8 { x } + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'x` + --> $DIR/feature-gate-in_band_lifetimes.rs:13:23 + | +13 | fn foo(x: &'x u8) -> &'x u8 { x } + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:25:12 + | +25 | impl<'a> X<'b> { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:27:27 + | +27 | fn inner_2(&self) -> &'b u8 { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:33:8 + | +33 | impl X<'b> { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:35:27 + | +35 | fn inner_3(&self) -> &'b u8 { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:43:9 + | +43 | impl Y<&'a u8> { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:45:25 + | +45 | fn inner(&self) -> &'a u8 { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:53:27 + | +53 | fn any_lifetime() -> &'b u8; + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:55:27 + | +55 | fn borrowed_lifetime(&'b self) -> &'b u8; + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:55:40 + | +55 | fn borrowed_lifetime(&'b self) -> &'b u8; + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:60:14 + | +60 | impl MyTrait<'a> for Y<&'a u8> { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:60:25 + | +60 | impl MyTrait<'a> for Y<&'a u8> { + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/feature-gate-in_band_lifetimes.rs:63:31 + | +63 | fn my_lifetime(&self) -> &'a u8 { self.0 } + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:65:27 + | +65 | fn any_lifetime() -> &'b u8 { &0 } + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:67:27 + | +67 | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/feature-gate-in_band_lifetimes.rs:67:40 + | +67 | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } + | ^^ undeclared lifetime + +error: aborting due to 17 previous errors + diff --git a/src/test/compile-fail/feature-gate-intrinsics.rs b/src/test/ui/feature-gate-intrinsics.rs index a4c09b21c90..a4c09b21c90 100644 --- a/src/test/compile-fail/feature-gate-intrinsics.rs +++ b/src/test/ui/feature-gate-intrinsics.rs diff --git a/src/test/ui/feature-gate-intrinsics.stderr b/src/test/ui/feature-gate-intrinsics.stderr new file mode 100644 index 00000000000..5382122e30e --- /dev/null +++ b/src/test/ui/feature-gate-intrinsics.stderr @@ -0,0 +1,21 @@ +error: intrinsics are subject to change + --> $DIR/feature-gate-intrinsics.rs:11:1 + | +11 | / extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change +12 | | fn bar(); +13 | | } + | |_^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: intrinsics are subject to change + --> $DIR/feature-gate-intrinsics.rs:15:1 + | +15 | / extern "rust-intrinsic" fn baz() { //~ ERROR intrinsics are subject to change +16 | | } + | |_^ + | + = help: add #![feature(intrinsics)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-lang-items.rs b/src/test/ui/feature-gate-lang-items.rs index 0435ff4c332..0435ff4c332 100644 --- a/src/test/compile-fail/feature-gate-lang-items.rs +++ b/src/test/ui/feature-gate-lang-items.rs diff --git a/src/test/ui/feature-gate-lang-items.stderr b/src/test/ui/feature-gate-lang-items.stderr new file mode 100644 index 00000000000..dab8ce23192 --- /dev/null +++ b/src/test/ui/feature-gate-lang-items.stderr @@ -0,0 +1,10 @@ +error: language items are subject to change + --> $DIR/feature-gate-lang-items.rs:11:1 + | +11 | #[lang="foo"] //~ ERROR language items are subject to change + | ^^^^^^^^^^^^^ + | + = help: add #![feature(lang_items)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-link-args.rs b/src/test/ui/feature-gate-link_args.rs index 82f5db3042b..bd48ac673dd 100644 --- a/src/test/compile-fail/gated-link-args.rs +++ b/src/test/ui/feature-gate-link_args.rs @@ -12,8 +12,6 @@ // feature gate, both when it occurs where expected (atop // `extern { }` blocks) and where unexpected. -// gate-test-link_args - // sidestep warning (which is correct, but misleading for // purposes of this test) #![allow(unused_attributes)] diff --git a/src/test/ui/feature-gate-link_args.stderr b/src/test/ui/feature-gate-link_args.stderr new file mode 100644 index 00000000000..d6d059007d1 --- /dev/null +++ b/src/test/ui/feature-gate-link_args.stderr @@ -0,0 +1,26 @@ +error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596) + --> $DIR/feature-gate-link_args.rs:22:1 + | +22 | #[link_args = "-l expected_use_case"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(link_args)] to the crate attributes to enable + +error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596) + --> $DIR/feature-gate-link_args.rs:26:1 + | +26 | #[link_args = "-l unexected_use_on_non_extern_item"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(link_args)] to the crate attributes to enable + +error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596) + --> $DIR/feature-gate-link_args.rs:19:1 + | +19 | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(link_args)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/link-cfg-gated.rs b/src/test/ui/feature-gate-link_cfg.rs index bb6fb9e3563..27918a27caf 100644 --- a/src/test/compile-fail/link-cfg-gated.rs +++ b/src/test/ui/feature-gate-link_cfg.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-link_cfg - #[link(name = "foo", cfg(foo))] //~^ ERROR: is feature gated extern {} diff --git a/src/test/ui/feature-gate-link_cfg.stderr b/src/test/ui/feature-gate-link_cfg.stderr new file mode 100644 index 00000000000..bbc52bd9d20 --- /dev/null +++ b/src/test/ui/feature-gate-link_cfg.stderr @@ -0,0 +1,10 @@ +error: is feature gated (see issue #37406) + --> $DIR/feature-gate-link_cfg.rs:11:1 + | +11 | #[link(name = "foo", cfg(foo))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(link_cfg)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-link-llvm-intrinsics.rs b/src/test/ui/feature-gate-link_llvm_intrinsics.rs index 681824ae71d..92a1b071437 100644 --- a/src/test/compile-fail/gated-link-llvm-intrinsics.rs +++ b/src/test/ui/feature-gate-link_llvm_intrinsics.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-link_llvm_intrinsics - extern { #[link_name = "llvm.sqrt.f32"] fn sqrt(x: f32) -> f32; diff --git a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr new file mode 100644 index 00000000000..b2e2caaa51a --- /dev/null +++ b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr @@ -0,0 +1,10 @@ +error: linking to LLVM intrinsics is experimental (see issue #29602) + --> $DIR/feature-gate-link_llvm_intrinsics.rs:13:5 + | +13 | fn sqrt(x: f32) -> f32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/linkage1.rs b/src/test/ui/feature-gate-linkage.rs index 1cf208f0215..555cc2b9a7a 100644 --- a/src/test/compile-fail/linkage1.rs +++ b/src/test/ui/feature-gate-linkage.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-linkage - extern { #[linkage = "extern_weak"] static foo: isize; //~^ ERROR: the `linkage` attribute is experimental and not portable diff --git a/src/test/ui/feature-gate-linkage.stderr b/src/test/ui/feature-gate-linkage.stderr new file mode 100644 index 00000000000..62d857ddf2c --- /dev/null +++ b/src/test/ui/feature-gate-linkage.stderr @@ -0,0 +1,10 @@ +error: the `linkage` attribute is experimental and not portable across platforms (see issue #29603) + --> $DIR/feature-gate-linkage.rs:12:5 + | +12 | #[linkage = "extern_weak"] static foo: isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(linkage)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-linker-flavor.rs b/src/test/ui/feature-gate-linker-flavor.rs index 955ec39cda1..955ec39cda1 100644 --- a/src/test/compile-fail/feature-gate-linker-flavor.rs +++ b/src/test/ui/feature-gate-linker-flavor.rs diff --git a/src/test/ui/feature-gate-linker-flavor.stderr b/src/test/ui/feature-gate-linker-flavor.stderr new file mode 100644 index 00000000000..383e75e3d17 --- /dev/null +++ b/src/test/ui/feature-gate-linker-flavor.stderr @@ -0,0 +1,10 @@ +error: the `#[used]` attribute is an experimental feature (see issue #40289) + --> $DIR/feature-gate-linker-flavor.rs:16:1 + | +16 | #[used] + | ^^^^^^^ + | + = help: add #![feature(used)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/log-syntax-gate.rs b/src/test/ui/feature-gate-log_syntax.rs index b9688af35dc..63c66e53c5e 100644 --- a/src/test/compile-fail/log-syntax-gate.rs +++ b/src/test/ui/feature-gate-log_syntax.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-log_syntax - fn main() { log_syntax!() //~ ERROR `log_syntax!` is not stable enough } diff --git a/src/test/ui/feature-gate-log_syntax.stderr b/src/test/ui/feature-gate-log_syntax.stderr new file mode 100644 index 00000000000..f1c0d305f6c --- /dev/null +++ b/src/test/ui/feature-gate-log_syntax.stderr @@ -0,0 +1,10 @@ +error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598) + --> $DIR/feature-gate-log_syntax.rs:12:5 + | +12 | log_syntax!() //~ ERROR `log_syntax!` is not stable enough + | ^^^^^^^^^^^^^ + | + = help: add #![feature(log_syntax)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/log-syntax-gate2.rs b/src/test/ui/feature-gate-log_syntax2.rs index dcbe7eefee5..dcbe7eefee5 100644 --- a/src/test/compile-fail/log-syntax-gate2.rs +++ b/src/test/ui/feature-gate-log_syntax2.rs diff --git a/src/test/ui/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gate-log_syntax2.stderr new file mode 100644 index 00000000000..b1bb5557eed --- /dev/null +++ b/src/test/ui/feature-gate-log_syntax2.stderr @@ -0,0 +1,10 @@ +error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598) + --> $DIR/feature-gate-log_syntax2.rs:14:20 + | +14 | println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(log_syntax)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-macro-vis-matcher.rs b/src/test/ui/feature-gate-macro-vis-matcher.rs index 5d6f2acea83..5d6f2acea83 100644 --- a/src/test/compile-fail/feature-gate-macro-vis-matcher.rs +++ b/src/test/ui/feature-gate-macro-vis-matcher.rs diff --git a/src/test/ui/feature-gate-macro-vis-matcher.stderr b/src/test/ui/feature-gate-macro-vis-matcher.stderr new file mode 100644 index 00000000000..09db5009165 --- /dev/null +++ b/src/test/ui/feature-gate-macro-vis-matcher.stderr @@ -0,0 +1,10 @@ +error: :vis fragment specifier is experimental and subject to change (see issue #41022) + --> $DIR/feature-gate-macro-vis-matcher.rs:14:19 + | +14 | macro_rules! m { ($v:vis) => {} } + | ^^^^^^ + | + = help: add #![feature(macro_vis_matcher)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-main.rs b/src/test/ui/feature-gate-main.rs index db1c1a94417..db1c1a94417 100644 --- a/src/test/compile-fail/feature-gate-main.rs +++ b/src/test/ui/feature-gate-main.rs diff --git a/src/test/ui/feature-gate-main.stderr b/src/test/ui/feature-gate-main.stderr new file mode 100644 index 00000000000..90cf12822c8 --- /dev/null +++ b/src/test/ui/feature-gate-main.stderr @@ -0,0 +1,10 @@ +error: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634) + --> $DIR/feature-gate-main.rs:12:1 + | +12 | fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may change over time + | ^^^^^^^^^^^ + | + = help: add #![feature(main)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-match_beginning_vert.rs b/src/test/ui/feature-gate-match_beginning_vert.rs index 9085563c99d..9085563c99d 100644 --- a/src/test/compile-fail/feature-gate-match_beginning_vert.rs +++ b/src/test/ui/feature-gate-match_beginning_vert.rs diff --git a/src/test/ui/feature-gate-match_beginning_vert.stderr b/src/test/ui/feature-gate-match_beginning_vert.stderr new file mode 100644 index 00000000000..88053adfafa --- /dev/null +++ b/src/test/ui/feature-gate-match_beginning_vert.stderr @@ -0,0 +1,26 @@ +error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) + --> $DIR/feature-gate-match_beginning_vert.rs:24:9 + | +24 | | A => println!("A"), + | ^ + | + = help: add #![feature(match_beginning_vert)] to the crate attributes to enable + +error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) + --> $DIR/feature-gate-match_beginning_vert.rs:26:9 + | +26 | | B | C => println!("BC!"), + | ^ + | + = help: add #![feature(match_beginning_vert)] to the crate attributes to enable + +error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101) + --> $DIR/feature-gate-match_beginning_vert.rs:28:9 + | +28 | | _ => {}, + | ^ + | + = help: add #![feature(match_beginning_vert)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-match_default_bindings.rs b/src/test/ui/feature-gate-match_default_bindings.rs index 4ee2c1e2936..4ee2c1e2936 100644 --- a/src/test/compile-fail/feature-gate-match_default_bindings.rs +++ b/src/test/ui/feature-gate-match_default_bindings.rs diff --git a/src/test/ui/feature-gate-match_default_bindings.stderr b/src/test/ui/feature-gate-match_default_bindings.stderr new file mode 100644 index 00000000000..d86e8248f08 --- /dev/null +++ b/src/test/ui/feature-gate-match_default_bindings.stderr @@ -0,0 +1,10 @@ +error: non-reference pattern used to match a reference (see issue #42640) + --> $DIR/feature-gate-match_default_bindings.rs:13:9 + | +13 | Some(n) => {}, + | ^^^^^^^ help: consider using a reference: `&Some(n)` + | + = help: add #![feature(match_default_bindings)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-may-dangle.rs b/src/test/ui/feature-gate-may-dangle.rs index 0bf1e93d9aa..0bf1e93d9aa 100644 --- a/src/test/compile-fail/feature-gate-may-dangle.rs +++ b/src/test/ui/feature-gate-may-dangle.rs diff --git a/src/test/ui/feature-gate-may-dangle.stderr b/src/test/ui/feature-gate-may-dangle.stderr new file mode 100644 index 00000000000..e51723d058e --- /dev/null +++ b/src/test/ui/feature-gate-may-dangle.stderr @@ -0,0 +1,10 @@ +error: may_dangle has unstable semantics and may be removed in the future (see issue #34761) + --> $DIR/feature-gate-may-dangle.rs:18:6 + | +18 | impl<#[may_dangle] A> Drop for Pt<A> { + | ^^^^^^^^^^^^^ + | + = help: add #![feature(dropck_eyepatch)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-naked_functions.rs b/src/test/ui/feature-gate-naked_functions.rs index 5eb41181027..ceb475e1192 100644 --- a/src/test/compile-fail/gated-naked_functions.rs +++ b/src/test/ui/feature-gate-naked_functions.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-naked_functions - #[naked] //~^ the `#[naked]` attribute is an experimental feature fn naked() {} diff --git a/src/test/ui/feature-gate-naked_functions.stderr b/src/test/ui/feature-gate-naked_functions.stderr new file mode 100644 index 00000000000..9655982574c --- /dev/null +++ b/src/test/ui/feature-gate-naked_functions.stderr @@ -0,0 +1,18 @@ +error: the `#[naked]` attribute is an experimental feature (see issue #32408) + --> $DIR/feature-gate-naked_functions.rs:11:1 + | +11 | #[naked] + | ^^^^^^^^ + | + = help: add #![feature(naked_functions)] to the crate attributes to enable + +error: the `#[naked]` attribute is an experimental feature (see issue #32408) + --> $DIR/feature-gate-naked_functions.rs:15:1 + | +15 | #[naked] + | ^^^^^^^^ + | + = help: add #![feature(naked_functions)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-needs-allocator.rs b/src/test/ui/feature-gate-needs-allocator.rs index 1809564f5de..1809564f5de 100644 --- a/src/test/compile-fail/feature-gate-needs-allocator.rs +++ b/src/test/ui/feature-gate-needs-allocator.rs diff --git a/src/test/ui/feature-gate-needs-allocator.stderr b/src/test/ui/feature-gate-needs-allocator.stderr new file mode 100644 index 00000000000..5124c10cb47 --- /dev/null +++ b/src/test/ui/feature-gate-needs-allocator.stderr @@ -0,0 +1,10 @@ +error: the `#[needs_allocator]` attribute is an experimental feature + --> $DIR/feature-gate-needs-allocator.rs:11:1 + | +11 | #![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(allocator_internals)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/ui/feature-gate-negate-unsigned.rs index 599e31341f2..599e31341f2 100644 --- a/src/test/compile-fail/feature-gate-negate-unsigned.rs +++ b/src/test/ui/feature-gate-negate-unsigned.rs diff --git a/src/test/ui/feature-gate-negate-unsigned.stderr b/src/test/ui/feature-gate-negate-unsigned.stderr new file mode 100644 index 00000000000..d4311594517 --- /dev/null +++ b/src/test/ui/feature-gate-negate-unsigned.stderr @@ -0,0 +1,14 @@ +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/feature-gate-negate-unsigned.rs:20:23 + | +20 | let _max: usize = -1; + | ^^ + +error[E0600]: cannot apply unary operator `-` to type `u8` + --> $DIR/feature-gate-negate-unsigned.rs:24:14 + | +24 | let _y = -x; + | ^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/never-disabled.rs b/src/test/ui/feature-gate-never_type.rs index fb6b34fcbb6..11b9f412957 100644 --- a/src/test/compile-fail/never-disabled.rs +++ b/src/test/ui/feature-gate-never_type.rs @@ -10,8 +10,6 @@ // Test that ! errors when used in illegal positions with feature(never_type) disabled -// gate-test-never_type - trait Foo { type Wub; } diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr new file mode 100644 index 00000000000..c242e613ead --- /dev/null +++ b/src/test/ui/feature-gate-never_type.stderr @@ -0,0 +1,42 @@ +error: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:17:17 + | +17 | type Ma = (u32, !, i32); //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:18:20 + | +18 | type Meeshka = Vec<!>; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:19:16 + | +19 | type Mow = &fn(!) -> !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:20:19 + | +20 | type Skwoz = &mut !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: The `!` type is experimental (see issue #35121) + --> $DIR/feature-gate-never_type.rs:23:16 + | +23 | type Wub = !; //~ ERROR type is experimental + | ^ + | + = help: add #![feature(never_type)] to the crate attributes to enable + +error: aborting due to 5 previous errors + diff --git a/src/test/compile-fail/feature-gate-no-debug-2.rs b/src/test/ui/feature-gate-no-debug-2.rs index b663c136ee5..b663c136ee5 100644 --- a/src/test/compile-fail/feature-gate-no-debug-2.rs +++ b/src/test/ui/feature-gate-no-debug-2.rs diff --git a/src/test/ui/feature-gate-no-debug-2.stderr b/src/test/ui/feature-gate-no-debug-2.stderr new file mode 100644 index 00000000000..231fc400115 --- /dev/null +++ b/src/test/ui/feature-gate-no-debug-2.stderr @@ -0,0 +1,14 @@ +error: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721 + --> $DIR/feature-gate-no-debug-2.rs:14:1 + | +14 | #[no_debug] //~ ERROR use of deprecated attribute `no_debug` + | ^^^^^^^^^^^ help: remove this attribute + | +note: lint level defined here + --> $DIR/feature-gate-no-debug-2.rs:11:9 + | +11 | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-no-debug.rs b/src/test/ui/feature-gate-no-debug.rs index d21493de50a..d21493de50a 100644 --- a/src/test/compile-fail/feature-gate-no-debug.rs +++ b/src/test/ui/feature-gate-no-debug.rs diff --git a/src/test/ui/feature-gate-no-debug.stderr b/src/test/ui/feature-gate-no-debug.stderr new file mode 100644 index 00000000000..83a8189c095 --- /dev/null +++ b/src/test/ui/feature-gate-no-debug.stderr @@ -0,0 +1,10 @@ +error: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721) + --> $DIR/feature-gate-no-debug.rs:13:1 + | +13 | #[no_debug] //~ ERROR the `#[no_debug]` attribute was + | ^^^^^^^^^^^ + | + = help: add #![feature(no_debug)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-no-core.rs b/src/test/ui/feature-gate-no_core.rs index 66b9c2e5670..0a55a8a78ce 100644 --- a/src/test/compile-fail/gated-no-core.rs +++ b/src/test/ui/feature-gate-no_core.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-no_core - #![no_core] //~ ERROR no_core is experimental fn main() {} diff --git a/src/test/ui/feature-gate-no_core.stderr b/src/test/ui/feature-gate-no_core.stderr new file mode 100644 index 00000000000..02e0b176249 --- /dev/null +++ b/src/test/ui/feature-gate-no_core.stderr @@ -0,0 +1,10 @@ +error: no_core is experimental (see issue #29639) + --> $DIR/feature-gate-no_core.rs:11:1 + | +11 | #![no_core] //~ ERROR no_core is experimental + | ^^^^^^^^^^^ + | + = help: add #![feature(no_core)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-non-ascii-idents.rs b/src/test/ui/feature-gate-non_ascii_idents.rs index 1dff22839ad..9e042c3a7d5 100644 --- a/src/test/compile-fail/gated-non-ascii-idents.rs +++ b/src/test/ui/feature-gate-non_ascii_idents.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-non_ascii_idents - extern crate core as bäz; //~ ERROR non-ascii idents use föö::bar; //~ ERROR non-ascii idents diff --git a/src/test/ui/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gate-non_ascii_idents.stderr new file mode 100644 index 00000000000..df6ce6b6162 --- /dev/null +++ b/src/test/ui/feature-gate-non_ascii_idents.stderr @@ -0,0 +1,122 @@ +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:11:1 + | +11 | extern crate core as bäz; //~ ERROR non-ascii idents + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:13:5 + | +13 | use föö::bar; //~ ERROR non-ascii idents + | ^^^^^^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:15:1 + | +15 | / mod föö { //~ ERROR non-ascii idents +16 | | pub fn bar() {} +17 | | } + | |_^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:19:1 + | +19 | / fn bär( //~ ERROR non-ascii idents +20 | | bäz: isize //~ ERROR non-ascii idents +21 | | ) { +22 | | let _ö: isize; //~ ERROR non-ascii idents +... | +26 | | } +27 | | } + | |_^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:20:5 + | +20 | bäz: isize //~ ERROR non-ascii idents + | ^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:22:9 + | +22 | let _ö: isize; //~ ERROR non-ascii idents + | ^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:25:10 + | +25 | (_ä, _) => {} //~ ERROR non-ascii idents + | ^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:29:1 + | +29 | / struct Föö { //~ ERROR non-ascii idents +30 | | föö: isize //~ ERROR non-ascii idents +31 | | } + | |_^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:30:5 + | +30 | föö: isize //~ ERROR non-ascii idents + | ^^^^^^^^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:33:1 + | +33 | / enum Bär { //~ ERROR non-ascii idents +34 | | Bäz { //~ ERROR non-ascii idents +35 | | qüx: isize //~ ERROR non-ascii idents +36 | | } +37 | | } + | |_^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:34:5 + | +34 | / Bäz { //~ ERROR non-ascii idents +35 | | qüx: isize //~ ERROR non-ascii idents +36 | | } + | |_____^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:35:9 + | +35 | qüx: isize //~ ERROR non-ascii idents + | ^^^^^^^^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/feature-gate-non_ascii_idents.rs:40:5 + | +40 | fn qüx(); //~ ERROR non-ascii idents + | ^^^^^^^^^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: aborting due to 13 previous errors + diff --git a/src/test/compile-fail/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gate-non_exhaustive.rs index d2711084a4d..d2711084a4d 100644 --- a/src/test/compile-fail/feature-gate-non_exhaustive.rs +++ b/src/test/ui/feature-gate-non_exhaustive.rs diff --git a/src/test/ui/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gate-non_exhaustive.stderr new file mode 100644 index 00000000000..775e65b90fa --- /dev/null +++ b/src/test/ui/feature-gate-non_exhaustive.stderr @@ -0,0 +1,10 @@ +error: non exhaustive is an experimental feature (see issue #44109) + --> $DIR/feature-gate-non_exhaustive.rs:13:1 + | +13 | #[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109) + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(non_exhaustive)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.rs index a837a7f213e..a837a7f213e 100644 --- a/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs +++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.rs diff --git a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr new file mode 100644 index 00000000000..e50e1b4c0b5 --- /dev/null +++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr @@ -0,0 +1,10 @@ +error: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite + --> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:11:1 + | +11 | #[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(omit_gdb_pretty_printer_section)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-on-unimplemented.rs b/src/test/ui/feature-gate-on-unimplemented.rs index 5d32bba6a76..5d32bba6a76 100644 --- a/src/test/compile-fail/feature-gate-on-unimplemented.rs +++ b/src/test/ui/feature-gate-on-unimplemented.rs diff --git a/src/test/ui/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gate-on-unimplemented.stderr new file mode 100644 index 00000000000..06944a14736 --- /dev/null +++ b/src/test/ui/feature-gate-on-unimplemented.stderr @@ -0,0 +1,10 @@ +error: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628) + --> $DIR/feature-gate-on-unimplemented.rs:14:1 + | +14 | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(on_unimplemented)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs b/src/test/ui/feature-gate-optin-builtin-traits.rs index 4c5502cec18..4c5502cec18 100644 --- a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs +++ b/src/test/ui/feature-gate-optin-builtin-traits.rs diff --git a/src/test/ui/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gate-optin-builtin-traits.stderr new file mode 100644 index 00000000000..c5e9614c29a --- /dev/null +++ b/src/test/ui/feature-gate-optin-builtin-traits.stderr @@ -0,0 +1,26 @@ +error: auto traits are experimental and possibly buggy (see issue #13231) + --> $DIR/feature-gate-optin-builtin-traits.rs:20:1 + | +20 | auto trait AutoDummyTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable + +error: auto trait implementations are experimental and possibly buggy (see issue #13231) + --> $DIR/feature-gate-optin-builtin-traits.rs:24:1 + | +24 | impl DummyTrait for .. {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable + +error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231) + --> $DIR/feature-gate-optin-builtin-traits.rs:27:1 + | +27 | impl !DummyTrait for DummyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs b/src/test/ui/feature-gate-overlapping_marker_traits.rs index d2aa4e59b5b..d2aa4e59b5b 100644 --- a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs +++ b/src/test/ui/feature-gate-overlapping_marker_traits.rs diff --git a/src/test/ui/feature-gate-overlapping_marker_traits.stderr b/src/test/ui/feature-gate-overlapping_marker_traits.stderr new file mode 100644 index 00000000000..9028b14fcd7 --- /dev/null +++ b/src/test/ui/feature-gate-overlapping_marker_traits.stderr @@ -0,0 +1,10 @@ +error[E0119]: conflicting implementations of trait `MyMarker`: + --> $DIR/feature-gate-overlapping_marker_traits.rs:16:1 + | +15 | impl<T: Display> MyMarker for T {} + | ---------------------------------- first implementation here +16 | impl<T: Debug> MyMarker for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-placement-expr.rs b/src/test/ui/feature-gate-placement-expr.rs index e3478876763..e3478876763 100644 --- a/src/test/compile-fail/feature-gate-placement-expr.rs +++ b/src/test/ui/feature-gate-placement-expr.rs diff --git a/src/test/ui/feature-gate-placement-expr.stderr b/src/test/ui/feature-gate-placement-expr.stderr new file mode 100644 index 00000000000..fdb7b506711 --- /dev/null +++ b/src/test/ui/feature-gate-placement-expr.stderr @@ -0,0 +1,10 @@ +error: placement-in expression syntax is experimental and subject to change. (see issue #27779) + --> $DIR/feature-gate-placement-expr.rs:24:13 + | +24 | let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental + | ^^^^^^^^^^^ + | + = help: add #![feature(placement_in_syntax)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-plugin.rs b/src/test/ui/feature-gate-plugin.rs index 3b5d7626ce3..3b5d7626ce3 100644 --- a/src/test/compile-fail/feature-gate-plugin.rs +++ b/src/test/ui/feature-gate-plugin.rs diff --git a/src/test/ui/feature-gate-plugin.stderr b/src/test/ui/feature-gate-plugin.stderr new file mode 100644 index 00000000000..b94d3299abc --- /dev/null +++ b/src/test/ui/feature-gate-plugin.stderr @@ -0,0 +1,10 @@ +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/feature-gate-plugin.rs:13:1 + | +13 | #![plugin(foo)] + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-plugin_registrar.rs b/src/test/ui/feature-gate-plugin_registrar.rs index 8d185d183b4..9cdebde7b7b 100644 --- a/src/test/compile-fail/gated-plugin_registrar.rs +++ b/src/test/ui/feature-gate-plugin_registrar.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-plugin_registrar - // Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar` // feature gate. diff --git a/src/test/ui/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gate-plugin_registrar.stderr new file mode 100644 index 00000000000..3710239142a --- /dev/null +++ b/src/test/ui/feature-gate-plugin_registrar.stderr @@ -0,0 +1,10 @@ +error: compiler plugins are experimental and possibly buggy (see issue #29597) + --> $DIR/feature-gate-plugin_registrar.rs:16:1 + | +16 | pub fn registrar() {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(plugin_registrar)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-prelude_import.rs b/src/test/ui/feature-gate-prelude_import.rs index 8bc3df247ec..8bc3df247ec 100644 --- a/src/test/compile-fail/feature-gate-prelude_import.rs +++ b/src/test/ui/feature-gate-prelude_import.rs diff --git a/src/test/ui/feature-gate-prelude_import.stderr b/src/test/ui/feature-gate-prelude_import.stderr new file mode 100644 index 00000000000..df44dfff40b --- /dev/null +++ b/src/test/ui/feature-gate-prelude_import.stderr @@ -0,0 +1,10 @@ +error: `#[prelude_import]` is for use by rustc only + --> $DIR/feature-gate-prelude_import.rs:11:1 + | +11 | #[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(prelude_import)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-profiler-runtime.rs b/src/test/ui/feature-gate-profiler-runtime.rs index c6b2cb2eb07..c6b2cb2eb07 100644 --- a/src/test/compile-fail/feature-gate-profiler-runtime.rs +++ b/src/test/ui/feature-gate-profiler-runtime.rs diff --git a/src/test/ui/feature-gate-profiler-runtime.stderr b/src/test/ui/feature-gate-profiler-runtime.stderr new file mode 100644 index 00000000000..c3165438cdb --- /dev/null +++ b/src/test/ui/feature-gate-profiler-runtime.stderr @@ -0,0 +1,10 @@ +error: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable + --> $DIR/feature-gate-profiler-runtime.rs:11:1 + | +11 | #![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(profiler_runtime)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-repr-simd.rs b/src/test/ui/feature-gate-repr-simd.rs index 429cec7ec90..429cec7ec90 100644 --- a/src/test/compile-fail/feature-gate-repr-simd.rs +++ b/src/test/ui/feature-gate-repr-simd.rs diff --git a/src/test/ui/feature-gate-repr-simd.stderr b/src/test/ui/feature-gate-repr-simd.stderr new file mode 100644 index 00000000000..a2ff06dd59f --- /dev/null +++ b/src/test/ui/feature-gate-repr-simd.stderr @@ -0,0 +1,10 @@ +error: SIMD types are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-repr-simd.rs:11:1 + | +11 | #[repr(simd)] //~ error: SIMD types are experimental + | ^^^^^^^^^^^^^ + | + = help: add #![feature(repr_simd)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-repr128.rs b/src/test/ui/feature-gate-repr128.rs index 96fffa6cdd0..96fffa6cdd0 100644 --- a/src/test/compile-fail/feature-gate-repr128.rs +++ b/src/test/ui/feature-gate-repr128.rs diff --git a/src/test/ui/feature-gate-repr128.stderr b/src/test/ui/feature-gate-repr128.stderr new file mode 100644 index 00000000000..2d32eda3b37 --- /dev/null +++ b/src/test/ui/feature-gate-repr128.stderr @@ -0,0 +1,13 @@ +error: repr with 128-bit type is unstable (see issue #35118) + --> $DIR/feature-gate-repr128.rs:12:1 + | +12 | / enum A { //~ ERROR repr with 128-bit type is unstable +13 | | //~| HELP: add #![feature(repr128)] +14 | | A(u64) +15 | | } + | |_^ + | + = help: add #![feature(repr128)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-repr_align.rs b/src/test/ui/feature-gate-repr_align.rs index 9591d367a2d..9591d367a2d 100644 --- a/src/test/compile-fail/feature-gate-repr_align.rs +++ b/src/test/ui/feature-gate-repr_align.rs diff --git a/src/test/ui/feature-gate-repr_align.stderr b/src/test/ui/feature-gate-repr_align.stderr new file mode 100644 index 00000000000..16fdc135a5f --- /dev/null +++ b/src/test/ui/feature-gate-repr_align.stderr @@ -0,0 +1,10 @@ +error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626) + --> $DIR/feature-gate-repr_align.rs:12:1 + | +12 | #[repr(align(64))] //~ error: the struct `#[repr(align(u16))]` attribute is experimental + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(repr_align)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gate-rustc-attrs.rs index 8cfd3e020c6..8cfd3e020c6 100644 --- a/src/test/compile-fail/feature-gate-rustc-attrs.rs +++ b/src/test/ui/feature-gate-rustc-attrs.rs diff --git a/src/test/ui/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gate-rustc-attrs.stderr new file mode 100644 index 00000000000..c818b57ef12 --- /dev/null +++ b/src/test/ui/feature-gate-rustc-attrs.stderr @@ -0,0 +1,26 @@ +error: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642) + --> $DIR/feature-gate-rustc-attrs.rs:15:1 + | +15 | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642) + --> $DIR/feature-gate-rustc-attrs.rs:16:1 + | +16 | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) + --> $DIR/feature-gate-rustc-attrs.rs:17:1 + | +17 | #[rustc_foo] + | ^^^^^^^^^^^^ + | + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gate-rustc-diagnostic-macros.rs index bbdf248780f..bbdf248780f 100644 --- a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs +++ b/src/test/ui/feature-gate-rustc-diagnostic-macros.rs diff --git a/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr new file mode 100644 index 00000000000..843879036ed --- /dev/null +++ b/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr @@ -0,0 +1,20 @@ +error: cannot find macro `__build_diagnostic_array!` in this scope + --> $DIR/feature-gate-rustc-diagnostic-macros.rs:22:1 + | +22 | __build_diagnostic_array!(DIAGNOSTICS); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find macro `__register_diagnostic!` in this scope + --> $DIR/feature-gate-rustc-diagnostic-macros.rs:14:1 + | +14 | __register_diagnostic!(E0001); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find macro `__diagnostic_used!` in this scope + --> $DIR/feature-gate-rustc-diagnostic-macros.rs:18:5 + | +18 | __diagnostic_used!(E0001); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-rustc_const_unstable.rs b/src/test/ui/feature-gate-rustc_const_unstable.rs index 38a3e15fd7e..38a3e15fd7e 100644 --- a/src/test/compile-fail/feature-gate-rustc_const_unstable.rs +++ b/src/test/ui/feature-gate-rustc_const_unstable.rs diff --git a/src/test/ui/feature-gate-rustc_const_unstable.stderr b/src/test/ui/feature-gate-rustc_const_unstable.stderr new file mode 100644 index 00000000000..c32abb8b857 --- /dev/null +++ b/src/test/ui/feature-gate-rustc_const_unstable.stderr @@ -0,0 +1,10 @@ +error: the `#[rustc_const_unstable]` attribute is an internal feature + --> $DIR/feature-gate-rustc_const_unstable.rs:18:1 + | +18 | #[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(rustc_const_unstable)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gate-sanitizer-runtime.rs index a18641d8246..a18641d8246 100644 --- a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs +++ b/src/test/ui/feature-gate-sanitizer-runtime.rs diff --git a/src/test/ui/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gate-sanitizer-runtime.stderr new file mode 100644 index 00000000000..b9a43f8098d --- /dev/null +++ b/src/test/ui/feature-gate-sanitizer-runtime.stderr @@ -0,0 +1,10 @@ +error: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable + --> $DIR/feature-gate-sanitizer-runtime.rs:11:1 + | +11 | #![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(sanitizer_runtime)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/ui/feature-gate-simd-ffi.rs index 31c055f229c..31c055f229c 100644 --- a/src/test/compile-fail/feature-gate-simd-ffi.rs +++ b/src/test/ui/feature-gate-simd-ffi.rs diff --git a/src/test/ui/feature-gate-simd-ffi.stderr b/src/test/ui/feature-gate-simd-ffi.stderr new file mode 100644 index 00000000000..fa47e1a2903 --- /dev/null +++ b/src/test/ui/feature-gate-simd-ffi.stderr @@ -0,0 +1,18 @@ +error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code + --> $DIR/feature-gate-simd-ffi.rs:20:17 + | +20 | fn baz() -> LocalSimd; //~ ERROR use of SIMD type + | ^^^^^^^^^ + | + = help: add #![feature(simd_ffi)] to the crate attributes to enable + +error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code + --> $DIR/feature-gate-simd-ffi.rs:21:15 + | +21 | fn qux(x: LocalSimd); //~ ERROR use of SIMD type + | ^^^^^^^^^ + | + = help: add #![feature(simd_ffi)] to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-simd.rs b/src/test/ui/feature-gate-simd.rs index 025eaca5533..025eaca5533 100644 --- a/src/test/compile-fail/feature-gate-simd.rs +++ b/src/test/ui/feature-gate-simd.rs diff --git a/src/test/ui/feature-gate-simd.stderr b/src/test/ui/feature-gate-simd.stderr new file mode 100644 index 00000000000..b3225d580bf --- /dev/null +++ b/src/test/ui/feature-gate-simd.stderr @@ -0,0 +1,10 @@ +error: SIMD types are experimental and possibly buggy (see issue #27731) + --> $DIR/feature-gate-simd.rs:14:1 + | +14 | #[repr(simd)] //~ ERROR SIMD types are experimental + | ^^^^^^^^^^^^^ + | + = help: add #![feature(repr_simd)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-slice-patterns.rs b/src/test/ui/feature-gate-slice-patterns.rs index 625cb2d3515..625cb2d3515 100644 --- a/src/test/compile-fail/feature-gate-slice-patterns.rs +++ b/src/test/ui/feature-gate-slice-patterns.rs diff --git a/src/test/ui/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gate-slice-patterns.stderr new file mode 100644 index 00000000000..e5ba318b336 --- /dev/null +++ b/src/test/ui/feature-gate-slice-patterns.stderr @@ -0,0 +1,10 @@ +error: slice pattern syntax is experimental (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:16:9 + | +16 | [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental + | ^^^^^^^^^^^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-staged_api.rs b/src/test/ui/feature-gate-staged_api.rs index 014a0aaaf68..014a0aaaf68 100644 --- a/src/test/compile-fail/feature-gate-staged_api.rs +++ b/src/test/ui/feature-gate-staged_api.rs diff --git a/src/test/ui/feature-gate-staged_api.stderr b/src/test/ui/feature-gate-staged_api.stderr new file mode 100644 index 00000000000..30593d45760 --- /dev/null +++ b/src/test/ui/feature-gate-staged_api.stderr @@ -0,0 +1,14 @@ +error: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-staged_api.rs:11:1 + | +11 | #![stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-staged_api.rs:18:1 + | +18 | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/feature-gate-start.rs b/src/test/ui/feature-gate-start.rs index 7a0924d8adf..7a0924d8adf 100644 --- a/src/test/compile-fail/feature-gate-start.rs +++ b/src/test/ui/feature-gate-start.rs diff --git a/src/test/ui/feature-gate-start.stderr b/src/test/ui/feature-gate-start.stderr new file mode 100644 index 00000000000..b36fae2aacf --- /dev/null +++ b/src/test/ui/feature-gate-start.stderr @@ -0,0 +1,10 @@ +error: a #[start] function is an experimental feature whose signature may change over time (see issue #29633) + --> $DIR/feature-gate-start.rs:12:1 + | +12 | fn foo() {} //~ ERROR: a #[start] function is an experimental feature + | ^^^^^^^^^^^ + | + = help: add #![feature(start)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/ui/feature-gate-static-nobundle.rs index 0d13a4937c4..0d13a4937c4 100644 --- a/src/test/compile-fail/feature-gate-static-nobundle.rs +++ b/src/test/ui/feature-gate-static-nobundle.rs diff --git a/src/test/ui/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gate-static-nobundle.stderr new file mode 100644 index 00000000000..052516fad76 --- /dev/null +++ b/src/test/ui/feature-gate-static-nobundle.stderr @@ -0,0 +1,10 @@ +error: kind="static-nobundle" is feature gated (see issue #37403) + --> $DIR/feature-gate-static-nobundle.rs:11:1 + | +11 | #[link(name="foo", kind="static-nobundle")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(static_nobundle)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-stmt_expr_attributes.rs b/src/test/ui/feature-gate-stmt_expr_attributes.rs index 831d8862e10..831d8862e10 100644 --- a/src/test/compile-fail/feature-gate-stmt_expr_attributes.rs +++ b/src/test/ui/feature-gate-stmt_expr_attributes.rs diff --git a/src/test/ui/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gate-stmt_expr_attributes.stderr new file mode 100644 index 00000000000..80910594d1c --- /dev/null +++ b/src/test/ui/feature-gate-stmt_expr_attributes.stderr @@ -0,0 +1,10 @@ +error: attributes on non-item statements and expressions are experimental. (see issue #15701) + --> $DIR/feature-gate-stmt_expr_attributes.rs:11:16 + | +11 | const X: i32 = #[allow(dead_code)] 8; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-target_feature.rs b/src/test/ui/feature-gate-target_feature.rs index 02db8a71d53..da2e41a0f5e 100644 --- a/src/test/compile-fail/gated-target_feature.rs +++ b/src/test/ui/feature-gate-target_feature.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-target_feature - #[target_feature = "+sse2"] //~^ the `#[target_feature]` attribute is an experimental feature fn foo() {} diff --git a/src/test/ui/feature-gate-target_feature.stderr b/src/test/ui/feature-gate-target_feature.stderr new file mode 100644 index 00000000000..8c89eabf753 --- /dev/null +++ b/src/test/ui/feature-gate-target_feature.stderr @@ -0,0 +1,10 @@ +error: the `#[target_feature]` attribute is an experimental feature + --> $DIR/feature-gate-target_feature.rs:11:1 + | +11 | #[target_feature = "+sse2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(target_feature)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-thread-local.rs b/src/test/ui/feature-gate-thread_local.rs index b02ce9b7ecb..f355c6562c8 100644 --- a/src/test/compile-fail/gated-thread-local.rs +++ b/src/test/ui/feature-gate-thread_local.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-thread_local - // Test that `#[thread_local]` attribute is gated by `thread_local` // feature gate. // diff --git a/src/test/ui/feature-gate-thread_local.stderr b/src/test/ui/feature-gate-thread_local.stderr new file mode 100644 index 00000000000..2608018528c --- /dev/null +++ b/src/test/ui/feature-gate-thread_local.stderr @@ -0,0 +1,10 @@ +error: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594) + --> $DIR/feature-gate-thread_local.rs:18:1 + | +18 | #[thread_local] //~ ERROR `#[thread_local]` is an experimental feature + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(thread_local)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/gated-trace_macros.rs b/src/test/ui/feature-gate-trace_macros.rs index 0b85b19f176..367ee6df50d 100644 --- a/src/test/compile-fail/gated-trace_macros.rs +++ b/src/test/ui/feature-gate-trace_macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-trace_macros - fn main() { trace_macros!(true); //~ ERROR: `trace_macros` is not stable } diff --git a/src/test/ui/feature-gate-trace_macros.stderr b/src/test/ui/feature-gate-trace_macros.stderr new file mode 100644 index 00000000000..aca74099b7d --- /dev/null +++ b/src/test/ui/feature-gate-trace_macros.stderr @@ -0,0 +1,10 @@ +error: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) + --> $DIR/feature-gate-trace_macros.rs:12:5 + | +12 | trace_macros!(true); //~ ERROR: `trace_macros` is not stable + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(trace_macros)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/type-ascription-feature-gate.rs b/src/test/ui/feature-gate-type_ascription.rs index bf4ca03069c..d3c07d653f4 100644 --- a/src/test/compile-fail/type-ascription-feature-gate.rs +++ b/src/test/ui/feature-gate-type_ascription.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-type_ascription - // Type ascription is feature gated fn main() { diff --git a/src/test/ui/feature-gate-type_ascription.stderr b/src/test/ui/feature-gate-type_ascription.stderr new file mode 100644 index 00000000000..d2a3ee2cf8f --- /dev/null +++ b/src/test/ui/feature-gate-type_ascription.stderr @@ -0,0 +1,10 @@ +error: type ascription is experimental (see issue #23416) + --> $DIR/feature-gate-type_ascription.rs:14:13 + | +14 | let a = 10: u8; //~ ERROR type ascription is experimental + | ^^^^^^ + | + = help: add #![feature(type_ascription)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/ui/feature-gate-unboxed-closures-manual-impls.rs index 5df309321d3..5df309321d3 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs +++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.rs diff --git a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr new file mode 100644 index 00000000000..280fc12f1a6 --- /dev/null +++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr @@ -0,0 +1,34 @@ +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:20:5 + | +20 | extern "rust-call" fn call(self, args: ()) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:25:5 + | +25 | extern "rust-call" fn call_once(self, args: ()) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:5 + | +30 | extern "rust-call" fn call_mut(&self, args: ()) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:5 + | +35 | extern "rust-call" fn call_once(&self, args: ()) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: aborting due to 4 previous errors + diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs b/src/test/ui/feature-gate-unboxed-closures-method-calls.rs index 253d1633b1c..253d1633b1c 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs +++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.rs diff --git a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr new file mode 100644 index 00000000000..1167bf0a696 --- /dev/null +++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr @@ -0,0 +1,26 @@ +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:14:7 + | +14 | f.call(()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:15:7 + | +15 | f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:16:7 + | +16 | f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^^^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.rs index 902b3c1774c..902b3c1774c 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs +++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.rs diff --git a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr new file mode 100644 index 00000000000..7eb491cebfe --- /dev/null +++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr @@ -0,0 +1,26 @@ +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:14:5 + | +14 | Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:15:5 + | +15 | FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^^^^^^^^^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: use of unstable library feature 'fn_traits' (see issue #29625) + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:16:5 + | +16 | FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits' + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(fn_traits)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-unboxed-closures.rs b/src/test/ui/feature-gate-unboxed-closures.rs index 40050217744..40050217744 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures.rs +++ b/src/test/ui/feature-gate-unboxed-closures.rs diff --git a/src/test/ui/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gate-unboxed-closures.stderr new file mode 100644 index 00000000000..b79165147e5 --- /dev/null +++ b/src/test/ui/feature-gate-unboxed-closures.stderr @@ -0,0 +1,12 @@ +error: rust-call ABI is subject to change (see issue #29625) + --> $DIR/feature-gate-unboxed-closures.rs:16:5 + | +16 | / extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { +17 | | a + b +18 | | } + | |_____^ + | + = help: add #![feature(unboxed_closures)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-underscore-lifetimes.rs b/src/test/ui/feature-gate-underscore-lifetimes.rs index 9da50c5c877..9da50c5c877 100644 --- a/src/test/compile-fail/feature-gate-underscore-lifetimes.rs +++ b/src/test/ui/feature-gate-underscore-lifetimes.rs diff --git a/src/test/ui/feature-gate-underscore-lifetimes.stderr b/src/test/ui/feature-gate-underscore-lifetimes.stderr new file mode 100644 index 00000000000..875b958aa88 --- /dev/null +++ b/src/test/ui/feature-gate-underscore-lifetimes.stderr @@ -0,0 +1,10 @@ +error: underscore lifetimes are unstable (see issue #44524) + --> $DIR/feature-gate-underscore-lifetimes.rs:13:23 + | +13 | fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable + | ^^ + | + = help: add #![feature(underscore_lifetimes)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/impl-trait/feature-gate-universal.rs b/src/test/ui/feature-gate-universal.rs index e5bdf3a42eb..e5bdf3a42eb 100644 --- a/src/test/compile-fail/impl-trait/feature-gate-universal.rs +++ b/src/test/ui/feature-gate-universal.rs diff --git a/src/test/ui/feature-gate-universal.stderr b/src/test/ui/feature-gate-universal.stderr new file mode 100644 index 00000000000..7f889f96224 --- /dev/null +++ b/src/test/ui/feature-gate-universal.stderr @@ -0,0 +1,10 @@ +error: `impl Trait` in argument position is experimental (see issue #34511) + --> $DIR/feature-gate-universal.rs:13:11 + | +13 | fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(universal_impl_trait)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/ui/feature-gate-unsized_tuple_coercion.rs index 4ddde011263..4ddde011263 100644 --- a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs +++ b/src/test/ui/feature-gate-unsized_tuple_coercion.rs diff --git a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr new file mode 100644 index 00000000000..f166b10613a --- /dev/null +++ b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr @@ -0,0 +1,10 @@ +error: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877) + --> $DIR/feature-gate-unsized_tuple_coercion.rs:12:24 + | +12 | let _ : &(Send,) = &((),); + | ^^^^^^ + | + = help: add #![feature(unsized_tuple_coercion)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/union/union-feature-gate.rs b/src/test/ui/feature-gate-untagged_unions.rs index 8a0490cdc6b..6533fddd947 100644 --- a/src/test/compile-fail/union/union-feature-gate.rs +++ b/src/test/ui/feature-gate-untagged_unions.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-untagged_unions - union U1 { // OK a: u8, } diff --git a/src/test/ui/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gate-untagged_unions.stderr new file mode 100644 index 00000000000..26b698912bc --- /dev/null +++ b/src/test/ui/feature-gate-untagged_unions.stderr @@ -0,0 +1,32 @@ +error: unions with non-`Copy` fields are unstable (see issue #32836) + --> $DIR/feature-gate-untagged_unions.rs:19:1 + | +19 | / union U3 { //~ ERROR unions with non-`Copy` fields are unstable +20 | | a: String, +21 | | } + | |_^ + | + = help: add #![feature(untagged_unions)] to the crate attributes to enable + +error: unions with non-`Copy` fields are unstable (see issue #32836) + --> $DIR/feature-gate-untagged_unions.rs:23:1 + | +23 | / union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable +24 | | a: T, +25 | | } + | |_^ + | + = help: add #![feature(untagged_unions)] to the crate attributes to enable + +error: unions with `Drop` implementations are unstable (see issue #32836) + --> $DIR/feature-gate-untagged_unions.rs:27:1 + | +27 | / union U5 { //~ ERROR unions with `Drop` implementations are unstable +28 | | a: u8, +29 | | } + | |_^ + | + = help: add #![feature(untagged_unions)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gate-unwind-attributes.rs index c8f9cd943cd..c8f9cd943cd 100644 --- a/src/test/compile-fail/feature-gate-unwind-attributes.rs +++ b/src/test/ui/feature-gate-unwind-attributes.rs diff --git a/src/test/ui/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gate-unwind-attributes.stderr new file mode 100644 index 00000000000..02d8bf914eb --- /dev/null +++ b/src/test/ui/feature-gate-unwind-attributes.stderr @@ -0,0 +1,10 @@ +error: #[unwind] is experimental + --> $DIR/feature-gate-unwind-attributes.rs:21:5 + | +21 | #[unwind] //~ ERROR #[unwind] is experimental + | ^^^^^^^^^ + | + = help: add #![feature(unwind_attributes)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-use_nested_groups.rs b/src/test/ui/feature-gate-use_nested_groups.rs index 56413a999d7..56413a999d7 100644 --- a/src/test/compile-fail/feature-gate-use_nested_groups.rs +++ b/src/test/ui/feature-gate-use_nested_groups.rs diff --git a/src/test/ui/feature-gate-use_nested_groups.stderr b/src/test/ui/feature-gate-use_nested_groups.stderr new file mode 100644 index 00000000000..79f1d1a168f --- /dev/null +++ b/src/test/ui/feature-gate-use_nested_groups.stderr @@ -0,0 +1,26 @@ +error: nested groups in `use` are experimental (see issue #44494) + --> $DIR/feature-gate-use_nested_groups.rs:27:12 + | +27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental + | ^^^^^^^^^^^^ + | + = help: add #![feature(use_nested_groups)] to the crate attributes to enable + +error: glob imports in `use` groups are experimental (see issue #44494) + --> $DIR/feature-gate-use_nested_groups.rs:27:16 + | +27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental + | ^ + | + = help: add #![feature(use_nested_groups)] to the crate attributes to enable + +error: paths in `use` groups are experimental (see issue #44494) + --> $DIR/feature-gate-use_nested_groups.rs:27:19 + | +27 | use a::{B, d::{*, g::H}}; //~ ERROR glob imports in `use` groups are experimental + | ^^^^ + | + = help: add #![feature(use_nested_groups)] to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate-used.rs b/src/test/ui/feature-gate-used.rs index 68679d7dac8..68679d7dac8 100644 --- a/src/test/compile-fail/feature-gate-used.rs +++ b/src/test/ui/feature-gate-used.rs diff --git a/src/test/ui/feature-gate-used.stderr b/src/test/ui/feature-gate-used.stderr new file mode 100644 index 00000000000..228cf12a08b --- /dev/null +++ b/src/test/ui/feature-gate-used.stderr @@ -0,0 +1,10 @@ +error: the `#[used]` attribute is an experimental feature (see issue #40289) + --> $DIR/feature-gate-used.rs:11:1 + | +11 | #[used] + | ^^^^^^^ + | + = help: add #![feature(used)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-wasm_import_memory.rs b/src/test/ui/feature-gate-wasm_import_memory.rs index a010ebb3551..a010ebb3551 100644 --- a/src/test/compile-fail/feature-gate-wasm_import_memory.rs +++ b/src/test/ui/feature-gate-wasm_import_memory.rs diff --git a/src/test/ui/feature-gate-wasm_import_memory.stderr b/src/test/ui/feature-gate-wasm_import_memory.stderr new file mode 100644 index 00000000000..c0486d0d5f5 --- /dev/null +++ b/src/test/ui/feature-gate-wasm_import_memory.stderr @@ -0,0 +1,10 @@ +error: wasm_import_memory attribute is currently unstable + --> $DIR/feature-gate-wasm_import_memory.rs:11:1 + | +11 | #![wasm_import_memory] //~ ERROR: currently unstable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(wasm_import_memory)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs index a34f98f0355..a34f98f0355 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-bench.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr new file mode 100644 index 00000000000..f7d5473f443 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr @@ -0,0 +1,4 @@ +error[E0601]: main function not found + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index ab2fe02bb14..ab2fe02bb14 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr new file mode 100644 index 00000000000..0e72442143b --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -0,0 +1,1354 @@ +warning: macro_escape is a deprecated synonym for macro_use + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1 + | +532 | #[macro_escape] + | ^^^^^^^^^^^^^^^ + +warning: macro_escape is a deprecated synonym for macro_use + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:17 + | +535 | mod inner { #![macro_escape] } + | ^^^^^^^^^^^^^^^^ + | + = help: consider an outer attribute, #[macro_use] mod ... + +warning: `#[must_use]` on functions is experimental (see issue #43302) + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5 + | +682 | #[must_use = "1400"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(fn_must_use)] to the crate attributes to enable + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33 + | +49 | #![warn (x5400)] //~ WARN unknown lint: `x5400` + | ^^^^^ + | +note: lint level defined here + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:28 + | +44 | #![warn(unused_attributes, unknown_lints)] + | ^^^^^^^^^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:33 + | +50 | #![allow (x5300)] //~ WARN unknown lint: `x5300` + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:51:33 + | +51 | #![forbid (x5200)] //~ WARN unknown lint: `x5200` + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:33 + | +52 | #![deny (x5100)] //~ WARN unknown lint: `x5100` + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:8 + | +114 | #[warn(x5400)] + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:25 + | +117 | mod inner { #![warn(x5400)] } + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12 + | +120 | #[warn(x5400)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12 + | +123 | #[warn(x5400)] struct S; + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12 + | +126 | #[warn(x5400)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:12 + | +129 | #[warn(x5400)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:9 + | +133 | #[allow(x5300)] + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:26 + | +136 | mod inner { #![allow(x5300)] } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13 + | +139 | #[allow(x5300)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13 + | +142 | #[allow(x5300)] struct S; + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13 + | +145 | #[allow(x5300)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:13 + | +148 | #[allow(x5300)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:10 + | +152 | #[forbid(x5200)] + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:27 + | +155 | mod inner { #![forbid(x5200)] } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14 + | +158 | #[forbid(x5200)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14 + | +161 | #[forbid(x5200)] struct S; + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14 + | +164 | #[forbid(x5200)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:14 + | +167 | #[forbid(x5200)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:8 + | +171 | #[deny(x5100)] + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:25 + | +174 | mod inner { #![deny(x5100)] } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12 + | +177 | #[deny(x5100)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12 + | +180 | #[deny(x5100)] struct S; + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12 + | +183 | #[deny(x5100)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:12 + | +186 | #[deny(x5100)] impl S { } + | ^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17 + | +193 | mod inner { #![macro_reexport="5000"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9 + | +44 | #![warn(unused_attributes, unknown_lints)] + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5 + | +196 | #[macro_reexport = "5000"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5 + | +199 | #[macro_reexport = "5000"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5 + | +202 | #[macro_reexport = "5000"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5 + | +205 | #[macro_reexport = "5000"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1 + | +190 | #[macro_reexport = "5000"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5 + | +213 | #[macro_use] fn f() { } + | ^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5 + | +216 | #[macro_use] struct S; + | ^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5 + | +219 | #[macro_use] type T = S; + | ^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:5 + | +222 | #[macro_use] impl S { } + | ^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:229:17 + | +229 | mod inner { #![macro_export="4800"] } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5 + | +232 | #[macro_export = "4800"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5 + | +235 | #[macro_export = "4800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5 + | +238 | #[macro_export = "4800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5 + | +241 | #[macro_export = "4800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:1 + | +226 | #[macro_export = "4800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:17 + | +248 | mod inner { #![plugin_registrar="4700"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 + | +253 | #[plugin_registrar = "4700"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5 + | +256 | #[plugin_registrar = "4700"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5 + | +259 | #[plugin_registrar = "4700"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:1 + | +245 | #[plugin_registrar = "4700"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:17 + | +266 | mod inner { #![main="4300"] } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 + | +271 | #[main = "4400"] struct S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 + | +274 | #[main = "4400"] type T = S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5 + | +277 | #[main = "4400"] impl S { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:1 + | +263 | #[main = "4400"] + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:17 + | +284 | mod inner { #![start="4300"] } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:5 + | +289 | #[start = "4300"] struct S; + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5 + | +292 | #[start = "4300"] type T = S; + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5 + | +295 | #[start = "4300"] impl S { } + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1 + | +281 | #[start = "4300"] + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:17 + | +334 | mod inner { #![simd="4000"] } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5 + | +337 | #[simd = "4000"] fn f() { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:5 + | +342 | #[simd = "4000"] type T = S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5 + | +345 | #[simd = "4000"] impl S { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:1 + | +331 | #[simd = "4000"] + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:17 + | +352 | mod inner { #![repr="3900"] } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 + | +355 | #[repr = "3900"] fn f() { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5 + | +360 | #[repr = "3900"] type T = S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5 + | +363 | #[repr = "3900"] impl S { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:1 + | +349 | #[repr = "3900"] + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5 + | +371 | #[path = "3800"] fn f() { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5 + | +374 | #[path = "3800"] struct S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5 + | +377 | #[path = "3800"] type T = S; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5 + | +380 | #[path = "3800"] impl S { } + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17 + | +387 | mod inner { #![abi="3700"] } + | ^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5 + | +390 | #[abi = "3700"] fn f() { } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5 + | +393 | #[abi = "3700"] struct S; + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5 + | +396 | #[abi = "3700"] type T = S; + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5 + | +399 | #[abi = "3700"] impl S { } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1 + | +384 | #[abi = "3700"] + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:17 + | +406 | mod inner { #![automatically_derived="3600"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5 + | +409 | #[automatically_derived = "3600"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5 + | +412 | #[automatically_derived = "3600"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:5 + | +415 | #[automatically_derived = "3600"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5 + | +418 | #[automatically_derived = "3600"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:1 + | +403 | #[automatically_derived = "3600"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: function is marked #[no_mangle], but not exported + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:27 + | +426 | #[no_mangle = "3500"] fn f() { } + | -^^^^^^^^^ + | | + | help: try making it public: `pub ` + | + = note: #[warn(private_no_mangle_fns)] on by default + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17 + | +439 | mod inner { #![no_link="3400"] } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5 + | +442 | #[no_link = "3400"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5 + | +445 | #[no_link = "3400"] struct S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5 + | +448 | #[no_link = "3400"]type T = S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5 + | +451 | #[no_link = "3400"] impl S { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1 + | +436 | #[no_link = "3400"] + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17 + | +458 | mod inner { #![should_panic="3200"] } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5 + | +461 | #[should_panic = "3200"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5 + | +464 | #[should_panic = "3200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5 + | +467 | #[should_panic = "3200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 + | +470 | #[should_panic = "3200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1 + | +455 | #[should_panic = "3200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17 + | +477 | mod inner { #![ignore="3100"] } + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5 + | +480 | #[ignore = "3100"] fn f() { } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5 + | +483 | #[ignore = "3100"] struct S; + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5 + | +486 | #[ignore = "3100"] type T = S; + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5 + | +489 | #[ignore = "3100"] impl S { } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1 + | +474 | #[ignore = "3100"] + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17 + | +496 | mod inner { #![no_implicit_prelude="3000"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 + | +499 | #[no_implicit_prelude = "3000"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5 + | +502 | #[no_implicit_prelude = "3000"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5 + | +505 | #[no_implicit_prelude = "3000"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5 + | +508 | #[no_implicit_prelude = "3000"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1 + | +493 | #[no_implicit_prelude = "3000"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:17 + | +515 | mod inner { #![reexport_test_harness_main="2900"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5 + | +518 | #[reexport_test_harness_main = "2900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5 + | +521 | #[reexport_test_harness_main = "2900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5 + | +524 | #[reexport_test_harness_main = "2900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5 + | +527 | #[reexport_test_harness_main = "2900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1 + | +512 | #[reexport_test_harness_main = "2900"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5 + | +538 | #[macro_escape] fn f() { } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5 + | +541 | #[macro_escape] struct S; + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5 + | +544 | #[macro_escape] type T = S; + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5 + | +547 | #[macro_escape] impl S { } + | ^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17 + | +555 | mod inner { #![no_std="2600"] } + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17 + | +555 | mod inner { #![no_std="2600"] } + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5 + | +559 | #[no_std = "2600"] fn f() { } + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5 + | +559 | #[no_std = "2600"] fn f() { } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5 + | +563 | #[no_std = "2600"] struct S; + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5 + | +563 | #[no_std = "2600"] struct S; + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5 + | +567 | #[no_std = "2600"] type T = S; + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5 + | +567 | #[no_std = "2600"] type T = S; + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5 + | +571 | #[no_std = "2600"] impl S { } + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5 + | +571 | #[no_std = "2600"] impl S { } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1 + | +551 | #[no_std = "2600"] + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1 + | +551 | #[no_std = "2600"] + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17 + | +711 | mod inner { #![crate_name="0900"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17 + | +711 | mod inner { #![crate_name="0900"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 + | +715 | #[crate_name = "0900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 + | +715 | #[crate_name = "0900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5 + | +719 | #[crate_name = "0900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5 + | +719 | #[crate_name = "0900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5 + | +723 | #[crate_name = "0900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5 + | +723 | #[crate_name = "0900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + | +727 | #[crate_name = "0900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + | +727 | #[crate_name = "0900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1 + | +707 | #[crate_name = "0900"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1 + | +707 | #[crate_name = "0900"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17 + | +736 | mod inner { #![crate_type="0800"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17 + | +736 | mod inner { #![crate_type="0800"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 + | +740 | #[crate_type = "0800"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 + | +740 | #[crate_type = "0800"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5 + | +744 | #[crate_type = "0800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5 + | +744 | #[crate_type = "0800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5 + | +748 | #[crate_type = "0800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5 + | +748 | #[crate_type = "0800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 + | +752 | #[crate_type = "0800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 + | +752 | #[crate_type = "0800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1 + | +732 | #[crate_type = "0800"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1 + | +732 | #[crate_type = "0800"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17 + | +761 | mod inner { #![feature(x0600)] } + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17 + | +761 | mod inner { #![feature(x0600)] } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 + | +765 | #[feature(x0600)] fn f() { } + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 + | +765 | #[feature(x0600)] fn f() { } + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5 + | +769 | #[feature(x0600)] struct S; + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5 + | +769 | #[feature(x0600)] struct S; + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5 + | +773 | #[feature(x0600)] type T = S; + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5 + | +773 | #[feature(x0600)] type T = S; + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5 + | +777 | #[feature(x0600)] impl S { } + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5 + | +777 | #[feature(x0600)] impl S { } + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1 + | +757 | #[feature(x0600)] + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1 + | +757 | #[feature(x0600)] + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17 + | +787 | mod inner { #![no_main="0400"] } + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17 + | +787 | mod inner { #![no_main="0400"] } + | ^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5 + | +791 | #[no_main = "0400"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5 + | +791 | #[no_main = "0400"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5 + | +795 | #[no_main = "0400"] struct S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5 + | +795 | #[no_main = "0400"] struct S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5 + | +799 | #[no_main = "0400"] type T = S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5 + | +799 | #[no_main = "0400"] type T = S; + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5 + | +803 | #[no_main = "0400"] impl S { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5 + | +803 | #[no_main = "0400"] impl S { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1 + | +783 | #[no_main = "0400"] + | ^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1 + | +783 | #[no_main = "0400"] + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17 + | +825 | mod inner { #![recursion_limit="0200"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17 + | +825 | mod inner { #![recursion_limit="0200"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5 + | +829 | #[recursion_limit="0200"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5 + | +829 | #[recursion_limit="0200"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5 + | +833 | #[recursion_limit="0200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5 + | +833 | #[recursion_limit="0200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5 + | +837 | #[recursion_limit="0200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5 + | +837 | #[recursion_limit="0200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5 + | +841 | #[recursion_limit="0200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5 + | +841 | #[recursion_limit="0200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1 + | +821 | #[recursion_limit="0200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1 + | +821 | #[recursion_limit="0200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17 + | +850 | mod inner { #![type_length_limit="0100"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17 + | +850 | mod inner { #![type_length_limit="0100"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5 + | +854 | #[type_length_limit="0100"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5 + | +854 | #[type_length_limit="0100"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5 + | +858 | #[type_length_limit="0100"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5 + | +858 | #[type_length_limit="0100"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5 + | +862 | #[type_length_limit="0100"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5 + | +862 | #[type_length_limit="0100"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5 + | +866 | #[type_length_limit="0100"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5 + | +866 | #[type_length_limit="0100"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1 + | +846 | #[type_length_limit="0100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1 + | +846 | #[type_length_limit="0100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 + | +53 | #![macro_reexport = "5000"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1 + | +55 | #![macro_export = "4800"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1 + | +56 | #![plugin_registrar = "4700"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1 + | +59 | #![main = "x4400"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 + | +60 | #![start = "x4300"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1 + | +63 | #![simd = "4000"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 + | +64 | #![repr = "3900"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1 + | +65 | #![path = "3800"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 + | +66 | #![abi = "3700"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1 + | +67 | #![automatically_derived = "3600"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 + | +69 | #![no_link = "3400"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1 + | +71 | #![should_panic = "3200"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 + | +72 | #![ignore = "3100"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1 + | +78 | #![proc_macro_derive = "2500"] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: compilation successful + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:1 + | +877 | / fn main() { //~ ERROR compilation successful +878 | | println!("Hello World"); +879 | | } + | |_^ + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs index 98da43c3a22..98da43c3a22 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-deprecated.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr new file mode 100644 index 00000000000..a413fcc56a0 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr @@ -0,0 +1,8 @@ +error: compilation successful + --> $DIR/issue-43106-gating-of-deprecated.rs:29:1 + | +29 | / fn main() { //~ ERROR compilation successful +30 | | println!("Hello World"); +31 | | } + | |_^ + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs index 2dbc6cb140d..2dbc6cb140d 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr new file mode 100644 index 00000000000..c5b33384b91 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr @@ -0,0 +1,20 @@ +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:14:14 + | +14 | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:18:14 + | +18 | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:22:14 + | +22 | #[derive(x3300)] + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs index e5293ebb94d..e5293ebb94d 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr new file mode 100644 index 00000000000..a0b12585f3c --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr @@ -0,0 +1,38 @@ +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:14:1 + | +14 | #![derive(Debug)] + | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:17:1 + | +17 | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:20:17 + | +20 | mod inner { #![derive(Debug)] } + | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:23:5 + | +23 | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:36:5 + | +36 | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-43106-gating-of-derive.rs:40:5 + | +40 | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs index 24e77bf60a8..24e77bf60a8 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-inline.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr new file mode 100644 index 00000000000..92bda4d0446 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr @@ -0,0 +1,43 @@ +error[E0518]: attribute should be applied to function + --> $DIR/issue-43106-gating-of-inline.rs:21:1 + | +21 | #[inline = "2100"] + | ^^^^^^^^^^^^^^^^^^ +22 | //~^ ERROR attribute should be applied to function +23 | / mod inline { +24 | | mod inner { #![inline="2100"] } +25 | | //~^ ERROR attribute should be applied to function +26 | | +... | +36 | | //~^ ERROR attribute should be applied to function +37 | | } + | |_- not a function + +error[E0518]: attribute should be applied to function + --> $DIR/issue-43106-gating-of-inline.rs:24:17 + | +24 | mod inner { #![inline="2100"] } + | ------------^^^^^^^^^^^^^^^^^-- not a function + +error[E0518]: attribute should be applied to function + --> $DIR/issue-43106-gating-of-inline.rs:29:5 + | +29 | #[inline = "2100"] struct S; + | ^^^^^^^^^^^^^^^^^^ --------- not a function + +error[E0518]: attribute should be applied to function + --> $DIR/issue-43106-gating-of-inline.rs:32:5 + | +32 | #[inline = "2100"] type T = S; + | ^^^^^^^^^^^^^^^^^^ ----------- not a function + +error[E0518]: attribute should be applied to function + --> $DIR/issue-43106-gating-of-inline.rs:35:5 + | +35 | #[inline = "2100"] impl S { } + | ^^^^^^^^^^^^^^^^^^ ---------- not a function + +error[E0601]: main function not found + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs index 3b2dbdefeba..3b2dbdefeba 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_escape.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr new file mode 100644 index 00000000000..60a9382bdb8 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr @@ -0,0 +1,12 @@ +warning: macro_escape is a deprecated synonym for macro_use + --> $DIR/issue-43106-gating-of-macro_escape.rs:16:1 + | +16 | #![macro_escape] + | ^^^^^^^^^^^^^^^^ + | + = help: consider an outer attribute, #[macro_use] mod ... + +error[E0601]: main function not found + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_use.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs index cf5619da3c7..cf5619da3c7 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_use.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr new file mode 100644 index 00000000000..2977384f62d --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr @@ -0,0 +1,20 @@ +error: arguments to macro_use are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:16:1 + | +16 | #![macro_use = "4900"] //~ ERROR arguments to macro_use are not allowed here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: arguments to macro_use are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:18:1 + | +18 | #[macro_use = "2700"] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: arguments to macro_use are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:21:17 + | +21 | mod inner { #![macro_use="2700"] } + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-proc_macro_derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs index 133f70e0f3b..133f70e0f3b 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-proc_macro_derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr new file mode 100644 index 00000000000..a76f0219f7a --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr @@ -0,0 +1,40 @@ +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:20:1 + | +20 | #[proc_macro_derive = "2500"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:28:17 + | +28 | mod inner { #![proc_macro_derive="2500"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:31:5 + | +31 | #[proc_macro_derive = "2500"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:34:5 + | +34 | #[proc_macro_derive = "2500"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:37:5 + | +37 | #[proc_macro_derive = "2500"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:40:5 + | +40 | #[proc_macro_derive = "2500"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0601]: main function not found + +error: aborting due to 7 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs index 10c13986349..10c13986349 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-rustc_deprecated.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr new file mode 100644 index 00000000000..6f6f587cb53 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr @@ -0,0 +1,46 @@ +error[E0601]: main function not found + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:17:1 + | +17 | #![rustc_deprecated = "1500"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:20:1 + | +20 | #[rustc_deprecated = "1500"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:23:17 + | +23 | mod inner { #![rustc_deprecated="1500"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5 + | +26 | #[rustc_deprecated = "1500"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:29:5 + | +29 | #[rustc_deprecated = "1500"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:32:5 + | +32 | #[rustc_deprecated = "1500"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:35:5 + | +35 | #[rustc_deprecated = "1500"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs index a6eaabf7a38..a6eaabf7a38 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-stable.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr new file mode 100644 index 00000000000..59f0431c708 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr @@ -0,0 +1,46 @@ +error[E0601]: main function not found + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:17:1 + | +17 | #![stable = "1300"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:20:1 + | +20 | #[stable = "1300"] + | ^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:23:17 + | +23 | mod inner { #![stable="1300"] } + | ^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:26:5 + | +26 | #[stable = "1300"] fn f() { } + | ^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:29:5 + | +29 | #[stable = "1300"] struct S; + | ^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:32:5 + | +32 | #[stable = "1300"] type T = S; + | ^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:35:5 + | +35 | #[stable = "1300"] impl S { } + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs index adcbfe77280..adcbfe77280 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-test.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr new file mode 100644 index 00000000000..f7d5473f443 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr @@ -0,0 +1,4 @@ +error[E0601]: main function not found + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs index ff0600deb19..ff0600deb19 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-unstable.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr new file mode 100644 index 00000000000..00cbc62ab47 --- /dev/null +++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr @@ -0,0 +1,46 @@ +error[E0601]: main function not found + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:17:1 + | +17 | #![unstable = "1200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:20:1 + | +20 | #[unstable = "1200"] + | ^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:23:17 + | +23 | mod inner { #![unstable="1200"] } + | ^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:26:5 + | +26 | #[unstable = "1200"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:29:5 + | +29 | #[unstable = "1200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:32:5 + | +32 | #[unstable = "1200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^ + +error: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:35:5 + | +35 | #[unstable = "1200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs new file mode 100644 index 00000000000..00a0c94d221 --- /dev/null +++ b/src/test/ui/nll/capture-ref-in-struct.rs @@ -0,0 +1,50 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Znll -Zborrowck=mir + +// Test that a structure which tries to store a pointer to `y` into +// `p` (indirectly) fails to compile. + +#![feature(rustc_attrs)] + +struct SomeStruct<'a, 'b: 'a> { + p: &'a mut &'b i32, + y: &'b i32, +} + +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + + let closure = SomeStruct { + p: &mut p, + y: &y, + }; + + closure.invoke(); + } + //~^ ERROR borrowed value does not live long enough [E0597] + + deref(p); +} + +impl<'a, 'b> SomeStruct<'a, 'b> { + fn invoke(self) { + *self.p = self.y; + } +} + +fn deref(_: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr new file mode 100644 index 00000000000..f10e52e05f1 --- /dev/null +++ b/src/test/ui/nll/capture-ref-in-struct.stderr @@ -0,0 +1,13 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/capture-ref-in-struct.rs:36:6 + | +28 | let y = 22; + | - temporary value created here +... +36 | } + | ^ temporary value dropped here while still borrowed + | + = note: consider using a `let` binding to increase its lifetime + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs new file mode 100644 index 00000000000..1e34aaf1ea0 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs @@ -0,0 +1,53 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test closure that: +// +// - takes an argument `y` with lifetime `'a` (in the code, it's anonymous) +// - stores `y` into another, longer-lived spot with lifetime `'b` +// +// Because `'a` and `'b` are two different, unrelated higher-ranked +// regions with no relationship to one another, this is an error. This +// error is reported by the closure itself and is not propagated to +// its creator: this is because `'a` and `'b` are higher-ranked +// (late-bound) regions and the closure is not allowed to propagate +// additional where clauses between higher-ranked regions, only those +// that appear free in its type (hence, we see it before the closure's +// "external requirements" report). + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = expect_sig(|p, y| *p = y); + //~^ ERROR free region `'_#4r` does not outlive free region `'_#3r` + //~| WARNING not reporting region error due to -Znll + closure(&mut p, &y); + } + + deref(p); +} + +fn expect_sig<F>(f: F) -> F + where F: FnMut(&mut &i32, &i32) +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr new file mode 100644 index 00000000000..c842d51a2ad --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -0,0 +1,40 @@ +warning: not reporting region error due to -Znll + --> $DIR/escape-argument-callee.rs:36:50 + | +36 | let mut closure = expect_sig(|p, y| *p = y); + | ^ + +error: free region `'_#4r` does not outlive free region `'_#3r` + --> $DIR/escape-argument-callee.rs:36:45 + | +36 | let mut closure = expect_sig(|p, y| *p = y); + | ^^^^^^ + +note: External requirements + --> $DIR/escape-argument-callee.rs:36:38 + | +36 | let mut closure = expect_sig(|p, y| *p = y); + | ^^^^^^^^^^^^^ + | + = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) i32)) + ] + = note: number of external vids: 1 + +note: No external requirements + --> $DIR/escape-argument-callee.rs:30:1 + | +30 | / fn test() { +31 | | let x = 44; +32 | | let mut p = &x; +33 | | +... | +42 | | deref(p); +43 | | } + | |_^ + | + = note: defining type: DefId(0/0:3 ~ escape_argument_callee[317d]::test[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs new file mode 100644 index 00000000000..1d8a916345e --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-argument.rs @@ -0,0 +1,52 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test closure that: +// +// - takes an argument `y` +// - stores `y` into another, longer-lived spot +// +// but is invoked with a spot that doesn't live long +// enough to store `y`. +// +// The error is reported in the caller: invoking the closure links the +// lifetime of the variable that is given as `y` (via subtyping) and +// thus forces the corresponding borrow to live too long. This is +// basically checking that the MIR type checker correctly enforces the +// closure signature. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = expect_sig(|p, y| *p = y); + closure(&mut p, &y); + } + //~^ ERROR borrowed value does not live long enough [E0597] + + deref(p); +} + +fn expect_sig<F>(f: F) -> F + where F: for<'a, 'b> FnMut(&'a mut &'b i32, &'b i32) +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr new file mode 100644 index 00000000000..e5c7139573e --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -0,0 +1,39 @@ +note: External requirements + --> $DIR/escape-argument.rs:36:38 + | +36 | let mut closure = expect_sig(|p, y| *p = y); + | ^^^^^^^^^^^^^ + | + = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32)) + ] + = note: number of external vids: 1 + +note: No external requirements + --> $DIR/escape-argument.rs:30:1 + | +30 | / fn test() { +31 | | let x = 44; +32 | | let mut p = &x; +33 | | +... | +41 | | deref(p); +42 | | } + | |_^ + | + = note: defining type: DefId(0/0:3 ~ escape_argument[317d]::test[0]) with substs [] + +error[E0597]: borrowed value does not live long enough + --> $DIR/escape-argument.rs:38:6 + | +35 | let y = 22; + | - temporary value created here +... +38 | } + | ^ temporary value dropped here while still borrowed + | + = note: consider using a `let` binding to increase its lifetime + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs new file mode 100644 index 00000000000..9f4585bfbab --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs @@ -0,0 +1,43 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// As in `escape-upvar-ref.rs`, test closure that: +// +// - captures a variable `y` +// - stores reference to `y` into another, longer-lived spot +// +// except that the closure does so via a second closure. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + + let mut closure = || { + let mut closure1 = || p = &y; + closure1(); + }; + + closure(); + } //~ ERROR borrowed value does not live long enough + + deref(p); +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr new file mode 100644 index 00000000000..201590f01f3 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -0,0 +1,61 @@ +note: External requirements + --> $DIR/escape-upvar-nested.rs:31:32 + | +31 | let mut closure1 = || p = &y; + | ^^^^^^^^^ + | + = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [ + i16, + extern "rust-call" fn(()), + &'_#1r mut &'_#2r i32, + &'_#3r i32 + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: External requirements + --> $DIR/escape-upvar-nested.rs:30:27 + | +30 | let mut closure = || { + | ___________________________^ +31 | | let mut closure1 = || p = &y; +32 | | closure1(); +33 | | }; + | |_________^ + | + = note: defining type: DefId(0/1:9 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + extern "rust-call" fn(()), + &'_#1r mut &'_#2r i32, + &'_#3r i32 + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: No external requirements + --> $DIR/escape-upvar-nested.rs:23:1 + | +23 | / fn test() { +24 | | let x = 44; +25 | | let mut p = &x; +26 | | +... | +38 | | deref(p); +39 | | } + | |_^ + | + = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs [] + +error[E0597]: borrowed value does not live long enough + --> $DIR/escape-upvar-nested.rs:36:6 + | +28 | let y = 22; + | - temporary value created here +... +36 | } //~ ERROR borrowed value does not live long enough + | ^ temporary value dropped here while still borrowed + | + = note: consider using a `let` binding to increase its lifetime + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs new file mode 100644 index 00000000000..548a5ae5969 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs @@ -0,0 +1,42 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test closure that: +// +// - captures a variable `y` by reference +// - stores that reference to `y` into another, longer-lived place (`p`) +// +// Both of these are upvars of reference type (the capture of `y` is +// of type `&'a i32`, the capture of `p` is of type `&mut &'b +// i32`). The closure thus computes a relationship between `'a` and +// `'b`. This relationship is propagated to the closure creator, +// which reports an error. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = || p = &y; + closure(); + } //~ ERROR borrowed value does not live long enough + + deref(p); +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr new file mode 100644 index 00000000000..47ba66ade65 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -0,0 +1,42 @@ +note: External requirements + --> $DIR/escape-upvar-ref.rs:33:27 + | +33 | let mut closure = || p = &y; + | ^^^^^^^^^ + | + = note: defining type: DefId(0/1:9 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + extern "rust-call" fn(()), + &'_#1r mut &'_#2r i32, + &'_#3r i32 + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: No external requirements + --> $DIR/escape-upvar-ref.rs:27:1 + | +27 | / fn test() { +28 | | let x = 44; +29 | | let mut p = &x; +30 | | +... | +37 | | deref(p); +38 | | } + | |_^ + | + = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs [] + +error[E0597]: borrowed value does not live long enough + --> $DIR/escape-upvar-ref.rs:35:6 + | +32 | let y = 22; + | - temporary value created here +... +35 | } //~ ERROR borrowed value does not live long enough + | ^ temporary value dropped here while still borrowed + | + = note: consider using a `let` binding to increase its lifetime + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs new file mode 100644 index 00000000000..c2f071cc029 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs @@ -0,0 +1,63 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test where we fail to approximate due to demanding a postdom +// relationship between our upper bounds. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'x: 'b +// 'c: 'y +// +// we have to prove that `'x: 'y`. We currently can only approximate +// via a postdominator -- hence we fail to choose between `'a` and +// `'b` here and report the error in the closure. +fn establish_relationships<'a, 'b, 'c, F>( + _cell_a: Cell<&'a u32>, + _cell_b: Cell<&'b u32>, + _cell_c: Cell<&'c u32>, + _closure: F, +) where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'b &'x u32>, // shows that 'x: 'b + Cell<&'y &'c u32>, // shows that 'c: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + establish_relationships( + cell_a, + cell_b, + cell_c, + |_outlives1, _outlives2, _outlives3, x, y| { + // Only works if 'x: 'y: + let p = x.get(); + //~^ WARN not reporting region error due to -Znll + demand_y(x, y, p) + //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r` + }, + ); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr new file mode 100644 index 00000000000..d581622c4c6 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -0,0 +1,46 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21 + | +55 | let p = x.get(); + | ^^^^^^^ + +error: free region `'_#5r` does not outlive free region `'_#6r` + --> $DIR/propagate-approximated-fail-no-postdom.rs:57:25 + | +57 | demand_y(x, y, p) + | ^ + +note: External requirements + --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9 + | +53 | / |_outlives1, _outlives2, _outlives3, x, y| { +54 | | // Only works if 'x: 'y: +55 | | let p = x.get(); +56 | | //~^ WARN not reporting region error due to -Znll +57 | | demand_y(x, y, p) +58 | | //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r` +59 | | }, + | |_________^ + | + = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>)) + ] + = note: number of external vids: 4 + +note: No external requirements + --> $DIR/propagate-approximated-fail-no-postdom.rs:48:1 + | +48 | / fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { +49 | | establish_relationships( +50 | | cell_a, +51 | | cell_b, +... | +60 | | ); +61 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs new file mode 100644 index 00000000000..76a0762461a --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs @@ -0,0 +1,64 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Rather convoluted setup where we infer a relationship between two +// free regions in the closure signature (`'a` and `'b`) on the basis +// of a relationship between two bound regions (`'x` and `'y`). +// +// The idea is that, thanks to invoking `demand_y`, `'x: 'y` must +// hold, where `'x` and `'y` are bound regions. The closure can't +// prove that directly, and because `'x` and `'y` are bound it cannot +// ask the caller to prove it either. But it has bounds on `'x` and +// `'y` in terms of `'a` and `'b`, and it can propagate a relationship +// between `'a` and `'b` to the caller. +// +// Note: the use of `Cell` here is to introduce invariance. One less +// variable. +// +// FIXME(#45827): The `supply` function *ought* to generate an error, but it +// currently does not. This is I believe a shortcoming of the MIR type +// checker: the closure inference is expressing the correct +// requirement, as you can see from the `#[rustc_regions]` output. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'b: 'y +// +// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must +// hold. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr new file mode 100644 index 00000000000..7553ac5b0c3 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -0,0 +1,36 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-ref.rs:60:9 + | +60 | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + +note: External requirements + --> $DIR/propagate-approximated-ref.rs:58:47 + | +58 | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ +59 | | // Only works if 'x: 'y: +60 | | demand_y(x, y, x.get()) +61 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>)) + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + +note: No external requirements + --> $DIR/propagate-approximated-ref.rs:57:1 + | +57 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +58 | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +59 | | // Only works if 'x: 'y: +60 | | demand_y(x, y, x.get()) +61 | | }); +62 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs [] + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs new file mode 100644 index 00000000000..0a47ee80256 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs @@ -0,0 +1,53 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case where we setup relationships like `'x: 'a` or `'a: 'x`, +// where `'x` is bound in closure type but `'a` is free. This forces +// us to approximate `'x` one way or the other. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +fn foo<'a, F>(_cell: Cell<&'a u32>, _f: F) +where + F: for<'x> FnOnce(Cell<&'a u32>, Cell<&'x u32>), +{ +} + +#[rustc_regions] +fn case1() { + let a = 0; + let cell = Cell::new(&a); + foo(cell, |cell_a, cell_x| { + //~^ WARNING not reporting region error due to -Znll + cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure + //~^ ERROR free region `'_#2r` does not outlive free region `'_#1r` + }) +} + +#[rustc_regions] +fn case2() { + let a = 0; + let cell = Cell::new(&a); + + // As you can see in the stderr output, this closure propoagates a + // requirement that `'a: 'static'. + // + // FIXME(#45827) However, because of shortcomings in the MIR type + // checker, this does not result in errors later on (yet). + foo(cell, |cell_a, cell_x| { + cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error + }) +} + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr new file mode 100644 index 00000000000..e2de72ffe93 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -0,0 +1,75 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:5 + | +31 | foo(cell, |cell_a, cell_x| { + | ^^^ + +error: free region `'_#2r` does not outlive free region `'_#1r` + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9 + | +33 | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure + | ^^^^^^ + +note: External requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15 + | +31 | foo(cell, |cell_a, cell_x| { + | _______________^ +32 | | //~^ WARNING not reporting region error due to -Znll +33 | | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure +34 | | //~^ ERROR free region `'_#2r` does not outlive free region `'_#1r` +35 | | }) + | |_____^ + | + = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [ + i32, + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>)) + ] + = note: number of external vids: 2 + +note: No external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1 + | +28 | / fn case1() { +29 | | let a = 0; +30 | | let cell = Cell::new(&a); +31 | | foo(cell, |cell_a, cell_x| { +... | +35 | | }) +36 | | } + | |_^ + | + = note: defining type: DefId(0/0:5 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs [] + +note: External requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:48:15 + | +48 | foo(cell, |cell_a, cell_x| { + | _______________^ +49 | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error +50 | | }) + | |_____^ + | + = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [ + i32, + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>)) + ] + = note: number of external vids: 2 + = note: where '_#1r: '_#0r + +note: No external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:39:1 + | +39 | / fn case2() { +40 | | let a = 0; +41 | | let cell = Cell::new(&a); +42 | | +... | +50 | | }) +51 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs new file mode 100644 index 00000000000..f776ddc8b15 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs @@ -0,0 +1,51 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case where we are trying to prove `'x: 'y` and are forced to +// approximate the shorter end-point (`'y`) to with `'static`. This is +// because `'y` is higher-ranked but we know of no relations to other +// regions. Note that `'static` shows up in the stderr output as `'0`. +// +// FIXME(#45827) Because of shortcomings in the MIR type checker, +// these errors are not (yet) reported. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// +// so the only way we can ensure that `'x: 'y` is to show that +// `'a: 'static`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr new file mode 100644 index 00000000000..8d1b9a94ea6 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -0,0 +1,36 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:47:9 + | +47 | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + +note: External requirements + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47 + | +45 | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | _______________________________________________^ +46 | | // Only works if 'x: 'y: +47 | | demand_y(x, y, x.get()) +48 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) u32>)) + ] + = note: number of external vids: 2 + = note: where '_#1r: '_#0r + +note: No external requirements + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 + | +44 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +45 | | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { +46 | | // Only works if 'x: 'y: +47 | | demand_y(x, y, x.get()) +48 | | }); +49 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs [] + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs new file mode 100644 index 00000000000..54b501c9ab6 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs @@ -0,0 +1,54 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case where we are trying to prove `'x: 'y` and are forced to +// approximate the shorter end-point (`'y`) to with `'static`. This is +// because `'y` is higher-ranked but we know of only irrelevant +// relations to other regions. Note that `'static` shows up in the +// stderr output as `'0`. +// +// FIXME(#45827) Because of shortcomings in the MIR type checker, +// these errors are not (yet) reported. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'y: 'b +// +// so the only way we can ensure that `'x: 'y` is to show that +// `'a: 'static`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'b &'y u32>, // shows that 'y: 'b + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr new file mode 100644 index 00000000000..9d318a63d8f --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -0,0 +1,36 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:50:9 + | +50 | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + +note: External requirements + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47 + | +48 | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ +49 | | // Only works if 'x: 'y: +50 | | demand_y(x, y, x.get()) +51 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>)) + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#0r + +note: No external requirements + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 + | +47 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +48 | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +49 | | // Only works if 'x: 'y: +50 | | demand_y(x, y, x.get()) +51 | | }); +52 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs [] + diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs new file mode 100644 index 00000000000..48d446b00af --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs @@ -0,0 +1,52 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A simpler variant of `outlives-from-argument` where cells are +// passed by value. +// +// This is simpler because there are no "extraneous" region +// relationships. In the 'main' variant, there are a number of +// anonymous regions as well. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'b: 'y +// +// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must +// hold. +fn establish_relationships<'a, 'b, F>(_cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'y &'b u32>, // shows that 'b: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: &'y u32) {} + +#[rustc_regions] +fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(outlives1, outlives2, x.get()) + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr new file mode 100644 index 00000000000..ae5ad6f4b96 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -0,0 +1,36 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-approximated-val.rs:48:9 + | +48 | demand_y(outlives1, outlives2, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: External requirements + --> $DIR/propagate-approximated-val.rs:46:45 + | +46 | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + | _____________________________________________^ +47 | | // Only works if 'x: 'y: +48 | | demand_y(outlives1, outlives2, x.get()) +49 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>)) + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + +note: No external requirements + --> $DIR/propagate-approximated-val.rs:45:1 + | +45 | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +46 | | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { +47 | | // Only works if 'x: 'y: +48 | | demand_y(outlives1, outlives2, x.get()) +49 | | }); +50 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs [] + diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs new file mode 100644 index 00000000000..a28b5f4c0f9 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs @@ -0,0 +1,59 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test where we might in theory be able to see that the relationship +// between two bound regions is true within closure and hence have no +// need to propagate; but in fact we do because identity of free +// regions is erased. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// In theory, callee knows that: +// +// 'x: 'a +// 'a: 'y +// +// and hence could satisfy that `'x: 'y` locally. However, in our +// checking, we ignore the precise free regions that come into the +// region and just assign each position a distinct universally bound +// region. Hence, we propagate a constraint to our caller that will +// wind up being solvable. +fn establish_relationships<'a, F>( + _cell_a: Cell<&'a u32>, + _closure: F, +) where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'y &'a u32>, // shows that 'a: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a>(cell_a: Cell<&'a u32>) { + establish_relationships( + cell_a, + |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + let p = x.get(); + demand_y(x, y, p) + }, + ); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr new file mode 100644 index 00000000000..64f3bb08c62 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -0,0 +1,37 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-despite-same-free-region.rs:53:21 + | +53 | let p = x.get(); + | ^^^^^^^ + +note: External requirements + --> $DIR/propagate-despite-same-free-region.rs:51:9 + | +51 | / |_outlives1, _outlives2, x, y| { +52 | | // Only works if 'x: 'y: +53 | | let p = x.get(); +54 | | demand_y(x, y, p) +55 | | }, + | |_________^ + | + = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>)) + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + +note: No external requirements + --> $DIR/propagate-despite-same-free-region.rs:48:1 + | +48 | / fn supply<'a>(cell_a: Cell<&'a u32>) { +49 | | establish_relationships( +50 | | cell_a, +51 | | |_outlives1, _outlives2, x, y| { +... | +56 | | ); +57 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs [] + diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs new file mode 100644 index 00000000000..4bbdcc44944 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs @@ -0,0 +1,53 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Similarly to escape-argument-callee, a test case where the closure +// requires a relationship between 2 unrelated higher-ranked regions, +// with no helpful relations between the HRRs and free regions. +// +// In this case, the error is reported by the closure itself. This is +// because it is unable to approximate the higher-ranked region `'x`, +// as it knows of no relationships between `'x` and any +// non-higher-ranked regions. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'b: 'y +// +// but this doesn't really help us in proving that `'x: 'y`, so closure gets an error. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#6r` does not outlive free region `'_#4r` + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr new file mode 100644 index 00000000000..6094f9aad81 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -0,0 +1,46 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 + | +47 | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: free region `'_#6r` does not outlive free region `'_#4r` + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:21 + | +47 | demand_y(x, y, x.get()) + | ^ + +note: External requirements + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47 + | +45 | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | _______________________________________________^ +46 | | // Only works if 'x: 'y: +47 | | demand_y(x, y, x.get()) +48 | | //~^ WARN not reporting region error due to -Znll +49 | | //~| ERROR free region `'_#6r` does not outlive free region `'_#4r` +50 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>)) + ] + = note: number of external vids: 2 + +note: No external requirements + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:44:1 + | +44 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +45 | | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { +46 | | // Only works if 'x: 'y: +47 | | demand_y(x, y, x.get()) +... | +50 | | }); +51 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs new file mode 100644 index 00000000000..69fad354792 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs @@ -0,0 +1,57 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Similarly to escape-argument-callee, a test case where the closure +// requires a relationship between 2 unrelated higher-ranked regions, +// with no helpful relations between the HRRs and free regions. +// +// In this case, the error is reported by the closure itself. This is +// because it is unable to approximate the higher-ranked region `'x`, +// as it only knows of regions that `'x` is outlived by, and none that +// `'x` outlives. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'a: 'x +// 'b: 'y +// +// but this doesn't really help us in proving that `'x: 'y`, so +// closure gets an error. In particular, we would need to know that +// `'x: 'a`, so that we could approximate `'x` "downwards" to `'a`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'x &'a u32>, // shows that 'a: 'x + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#5r` does not outlive free region `'_#7r` + }); +} + +fn main() {} diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr new file mode 100644 index 00000000000..6658ee63abd --- /dev/null +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -0,0 +1,46 @@ +warning: not reporting region error due to -Znll + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 + | +51 | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: free region `'_#5r` does not outlive free region `'_#7r` + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:21 + | +51 | demand_y(x, y, x.get()) + | ^ + +note: External requirements + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47 + | +49 | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ +50 | | // Only works if 'x: 'y: +51 | | demand_y(x, y, x.get()) +52 | | //~^ WARN not reporting region error due to -Znll +53 | | //~| ERROR free region `'_#5r` does not outlive free region `'_#7r` +54 | | }); + | |_____^ + | + = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>)) + ] + = note: number of external vids: 3 + +note: No external requirements + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:48:1 + | +48 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { +49 | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +50 | | // Only works if 'x: 'y: +51 | | demand_y(x, y, x.get()) +... | +54 | | }); +55 | | } + | |_^ + | + = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs new file mode 100644 index 00000000000..c61cf8a940f --- /dev/null +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +fn foo(x: &u32) -> &'static u32 { + &*x + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#1r` does not outlive free region `ReStatic` +} + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr new file mode 100644 index 00000000000..ef7ea923912 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -0,0 +1,14 @@ +warning: not reporting region error due to -Znll + --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5 + | +19 | &*x + | ^^^ + +error: free region `'_#1r` does not outlive free region `ReStatic` + --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5 + | +19 | &*x + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs new file mode 100644 index 00000000000..fcda5c5420b --- /dev/null +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +fn foo<'a>(x: &'a u32) -> &'static u32 { + &*x + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#1r` does not outlive free region `ReStatic` +} + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr new file mode 100644 index 00000000000..6dcb8e7cf12 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -0,0 +1,14 @@ +warning: not reporting region error due to -Znll + --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 + | +19 | &*x + | ^^^ + +error: free region `'_#1r` does not outlive free region `ReStatic` + --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 + | +19 | &*x + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/named-region-basic.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs index 001ce41c277..c1e4dee0065 100644 --- a/src/test/ui/nll/named-region-basic.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs @@ -13,12 +13,12 @@ // a variety of errors from the older, AST-based machinery (notably // borrowck), and then we get the NLL error at the end. -// compile-flags:-Znll +// compile-flags:-Znll -Zborrowck=mir -Zverbose fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { - &*x //~ ERROR free region `'a` does not outlive `'b` - //~^ ERROR `*x` does not live long enough - //~| WARN not reporting region error due to -Znll + &*x + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#1r` does not outlive free region `'_#2r` } fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr new file mode 100644 index 00000000000..c1b2f440309 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -0,0 +1,14 @@ +warning: not reporting region error due to -Znll + --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5 + | +19 | &*x + | ^^^ + +error: free region `'_#1r` does not outlive free region `'_#2r` + --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5 + | +19 | &*x + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/feature-gate-abi-sysv64.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs index 2a4aae8c06b..ffb1935e75e 100644 --- a/src/test/compile-fail/feature-gate-abi-sysv64.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that the sysv64 ABI cannot be used when abi-sysv64 feature -// gate is not used. +// Basic test for free regions in the NLL code. This test does not +// report an error because of the (implied) bound that `'b: 'a`. -extern "sysv64" fn foo() {} -//~^ ERROR sysv64 ABI is experimental and subject to change +// compile-flags:-Znll -Zborrowck=mir -Zverbose +// must-compile-successfully -fn main() { - foo(); +#![allow(warnings)] + +fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 { + &**x } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs new file mode 100644 index 00000000000..9314bbf9432 --- /dev/null +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs @@ -0,0 +1,34 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test closure that takes two references and is supposed to return +// the first, but actually returns the second. This should fail within +// the closure. + +// compile-flags:-Znll -Zborrowck=mir -Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + expect_sig(|a, b| b); // ought to return `a` + //~^ WARN not reporting region error due to -Znll + //~| ERROR free region `'_#3r` does not outlive free region `'_#2r` +} + +fn expect_sig<F>(f: F) -> F + where F: for<'a> FnMut(&'a i32, &i32) -> &'a i32 +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr new file mode 100644 index 00000000000..8999f69e8de --- /dev/null +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -0,0 +1,38 @@ +warning: not reporting region error due to -Znll + --> $DIR/return-wrong-bound-region.rs:21:23 + | +21 | expect_sig(|a, b| b); // ought to return `a` + | ^ + +error: free region `'_#3r` does not outlive free region `'_#2r` + --> $DIR/return-wrong-bound-region.rs:21:23 + | +21 | expect_sig(|a, b| b); // ought to return `a` + | ^ + +note: External requirements + --> $DIR/return-wrong-bound-region.rs:21:16 + | +21 | expect_sig(|a, b| b); // ought to return `a` + | ^^^^^^^^ + | + = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32 + ] + = note: number of external vids: 1 + +note: No external requirements + --> $DIR/return-wrong-bound-region.rs:20:1 + | +20 | / fn test() { +21 | | expect_sig(|a, b| b); // ought to return `a` +22 | | //~^ WARN not reporting region error due to -Znll +23 | | //~| ERROR free region `'_#3r` does not outlive free region `'_#2r` +24 | | } + | |_^ + | + = note: defining type: DefId(0/0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs [] + +error: aborting due to previous error + diff --git a/src/test/ui/nll/named-region-basic.stderr b/src/test/ui/nll/named-region-basic.stderr deleted file mode 100644 index 9c1de6c366c..00000000000 --- a/src/test/ui/nll/named-region-basic.stderr +++ /dev/null @@ -1,31 +0,0 @@ -warning: not reporting region error due to -Znll - --> $DIR/named-region-basic.rs:19:5 - | -19 | &*x //~ ERROR free region `'a` does not outlive `'b` - | ^^^ - -error[E0597]: `*x` does not live long enough - --> $DIR/named-region-basic.rs:19:6 - | -19 | &*x //~ ERROR free region `'a` does not outlive `'b` - | ^^ does not live long enough - | - = note: borrowed value must be valid for the static lifetime... -note: ...but borrowed value is only valid for the lifetime 'a as defined on the function body at 18:1 - --> $DIR/named-region-basic.rs:18:1 - | -18 | / fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { -19 | | &*x //~ ERROR free region `'a` does not outlive `'b` -20 | | //~^ ERROR `*x` does not live long enough -21 | | //~| WARN not reporting region error due to -Znll -22 | | } - | |_^ - -error: free region `'a` does not outlive `'b` - --> $DIR/named-region-basic.rs:19:5 - | -19 | &*x //~ ERROR free region `'a` does not outlive `'b` - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs b/src/test/ui/specialization-feature-gate-default.rs index 3a01ecdf9db..3a01ecdf9db 100644 --- a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs +++ b/src/test/ui/specialization-feature-gate-default.rs diff --git a/src/test/ui/specialization-feature-gate-default.stderr b/src/test/ui/specialization-feature-gate-default.stderr new file mode 100644 index 00000000000..e17d1308385 --- /dev/null +++ b/src/test/ui/specialization-feature-gate-default.stderr @@ -0,0 +1,10 @@ +error: specialization is unstable (see issue #31844) + --> $DIR/specialization-feature-gate-default.rs:20:5 + | +20 | default fn foo(&self) {} //~ ERROR specialization is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(specialization)] to the crate attributes to enable + +error: aborting due to previous error + diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs b/src/test/ui/specialization-feature-gate-overlap.rs index 5eb48eab15e..5eb48eab15e 100644 --- a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs +++ b/src/test/ui/specialization-feature-gate-overlap.rs diff --git a/src/test/ui/specialization-feature-gate-overlap.stderr b/src/test/ui/specialization-feature-gate-overlap.stderr new file mode 100644 index 00000000000..7fe2891c908 --- /dev/null +++ b/src/test/ui/specialization-feature-gate-overlap.stderr @@ -0,0 +1,15 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `u8`: + --> $DIR/specialization-feature-gate-overlap.rs:23:1 + | +19 | / impl<T> Foo for T { +20 | | fn foo(&self) {} +21 | | } + | |_- first implementation here +22 | +23 | / impl Foo for u8 { //~ ERROR E0119 +24 | | fn foo(&self) {} +25 | | } + | |_^ conflicting implementation for `u8` + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 660462ad419..48c3c5c8198 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -13,7 +13,7 @@ use std::fmt; use std::str::FromStr; use std::path::PathBuf; -use test::ColorConfig; +use test::{ColorConfig, TestPaths}; #[derive(Clone, Copy, PartialEq, Debug)] pub enum Mode { @@ -221,3 +221,17 @@ pub struct Config { pub llvm_cxxflags: String, pub nodejs: Option<String>, } + +/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`. +pub fn expected_output_path(testpaths: &TestPaths, revision: Option<&str>, kind: &str) -> PathBuf { + assert!(UI_EXTENSIONS.contains(&kind)); + let extension = match revision { + Some(r) => format!("{}.{}", r, kind), + None => kind.to_string(), + }; + testpaths.file.with_extension(extension) +} + +pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT]; +pub const UI_STDERR: &str = "stderr"; +pub const UI_STDOUT: &str = "stdout"; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c853d53829c..e7851c36327 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -26,6 +26,7 @@ pub struct EarlyProps { pub ignore: bool, pub should_fail: bool, pub aux: Vec<String>, + pub revisions: Vec<String>, } impl EarlyProps { @@ -34,6 +35,7 @@ impl EarlyProps { ignore: false, should_fail: false, aux: Vec::new(), + revisions: vec![], }; iter_header(testfile, @@ -50,6 +52,10 @@ impl EarlyProps { props.aux.push(s); } + if let Some(r) = config.parse_revisions(ln) { + props.revisions.extend(r); + } + props.should_fail = props.should_fail || config.parse_name_directive(ln, "should-fail"); }); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 6da37df1927..fac3b71f82c 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -9,22 +9,20 @@ // except according to those terms. #![crate_name = "compiletest"] - #![feature(test)] #![feature(slice_rotate)] - #![deny(warnings)] +extern crate diff; +extern crate env_logger; +extern crate filetime; +extern crate getopts; #[cfg(unix)] extern crate libc; -extern crate test; -extern crate getopts; -extern crate rustc_serialize; #[macro_use] extern crate log; -extern crate env_logger; -extern crate filetime; -extern crate diff; +extern crate rustc_serialize; +extern crate test; use std::env; use std::ffi::OsString; @@ -35,8 +33,9 @@ use std::process::Command; use filetime::FileTime; use getopts::Options; use common::Config; -use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode}; -use test::{TestPaths, ColorConfig}; +use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; +use common::{expected_output_path, UI_EXTENSIONS}; +use test::{ColorConfig, TestPaths}; use util::logv; use self::header::EarlyProps; @@ -63,53 +62,168 @@ fn main() { run_tests(&config); } -pub fn parse_config(args: Vec<String> ) -> Config { - +pub fn parse_config(args: Vec<String>) -> Config { let mut opts = Options::new(); - opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") - .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") - .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") - .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") - .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH") - .reqopt("", "docck-python", "path to python to use for doc tests", "PATH") - .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM") - .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind") - .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR") + opts.reqopt( + "", + "compile-lib-path", + "path to host shared libraries", + "PATH", + ).reqopt( + "", + "run-lib-path", + "path to target shared libraries", + "PATH", + ) + .reqopt( + "", + "rustc-path", + "path to rustc to use for compiling", + "PATH", + ) + .optopt( + "", + "rustdoc-path", + "path to rustdoc to use for compiling", + "PATH", + ) + .reqopt( + "", + "lldb-python", + "path to python to use for doc tests", + "PATH", + ) + .reqopt( + "", + "docck-python", + "path to python to use for doc tests", + "PATH", + ) + .optopt( + "", + "valgrind-path", + "path to Valgrind executable for Valgrind tests", + "PROGRAM", + ) + .optflag( + "", + "force-valgrind", + "fail if Valgrind tests cannot be run under Valgrind", + ) + .optopt( + "", + "llvm-filecheck", + "path to LLVM's FileCheck binary", + "DIR", + ) .reqopt("", "src-base", "directory to scan for test files", "PATH") - .reqopt("", "build-base", "directory to deposit test outputs", "PATH") - .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET") - .reqopt("", "mode", "which sort of compile tests to run", - "(compile-fail|parse-fail|run-fail|run-pass|\ - run-pass-valgrind|pretty|debug-info|incremental|mir-opt)") + .reqopt( + "", + "build-base", + "directory to deposit test outputs", + "PATH", + ) + .reqopt( + "", + "stage-id", + "the target-stage identifier", + "stageN-TARGET", + ) + .reqopt( + "", + "mode", + "which sort of compile tests to run", + "(compile-fail|parse-fail|run-fail|run-pass|\ + run-pass-valgrind|pretty|debug-info|incremental|mir-opt)", + ) .optflag("", "ignored", "run tests marked as ignored") .optflag("", "exact", "filters match exactly") - .optopt("", "runtool", "supervisor program to run tests under \ - (eg. emulator, valgrind)", "PROGRAM") - .optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") - .optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optopt( + "", + "runtool", + "supervisor program to run tests under \ + (eg. emulator, valgrind)", + "PROGRAM", + ) + .optopt( + "", + "host-rustcflags", + "flags to pass to rustc for host", + "FLAGS", + ) + .optopt( + "", + "target-rustcflags", + "flags to pass to rustc for target", + "FLAGS", + ) .optflag("", "verbose", "run tests verbosely, showing all output") - .optflag("", "quiet", "print one character per test instead of one line") + .optflag( + "", + "quiet", + "print one character per test instead of one line", + ) .optopt("", "color", "coloring: auto, always, never", "WHEN") .optopt("", "logfile", "file to log test execution to", "FILE") .optopt("", "target", "the target to build for", "TARGET") .optopt("", "host", "the host to build for", "HOST") - .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH") - .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING") - .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING") + .optopt( + "", + "gdb", + "path to GDB to use for GDB debuginfo tests", + "PATH", + ) + .optopt( + "", + "lldb-version", + "the version of LLDB used", + "VERSION STRING", + ) + .optopt( + "", + "llvm-version", + "the version of LLVM used", + "VERSION STRING", + ) .optflag("", "system-llvm", "is LLVM the system LLVM") - .optopt("", "android-cross-path", "Android NDK standalone path", "PATH") + .optopt( + "", + "android-cross-path", + "Android NDK standalone path", + "PATH", + ) .optopt("", "adb-path", "path to the android debugger", "PATH") - .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH") - .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH") + .optopt( + "", + "adb-test-dir", + "path to tests for the android debugger", + "PATH", + ) + .optopt( + "", + "lldb-python-dir", + "directory containing LLDB's python module", + "PATH", + ) .reqopt("", "cc", "path to a C compiler", "PATH") .reqopt("", "cxx", "path to a C++ compiler", "PATH") .reqopt("", "cflags", "flags for the C compiler", "FLAGS") .optopt("", "ar", "path to an archiver", "PATH") .optopt("", "linker", "path to a linker", "PATH") - .reqopt("", "llvm-components", "list of LLVM components built in", "LIST") + .reqopt( + "", + "llvm-components", + "list of LLVM components built in", + "LIST", + ) .reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS") .optopt("", "nodejs", "the name of nodejs", "PATH") - .optopt("", "remote-test-client", "path to the remote test client", "PATH") + .optopt( + "", + "remote-test-client", + "path to the remote test client", + "PATH", + ) .optflag("h", "help", "show this message"); let (argv0, args_) = args.split_first().unwrap(); @@ -120,11 +234,10 @@ pub fn parse_config(args: Vec<String> ) -> Config { panic!() } - let matches = - &match opts.parse(args_) { - Ok(m) => m, - Err(f) => panic!("{:?}", f) - }; + let matches = &match opts.parse(args_) { + Ok(m) => m, + Err(f) => panic!("{:?}", f), + }; if matches.opt_present("h") || matches.opt_present("help") { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); @@ -154,7 +267,10 @@ pub fn parse_config(args: Vec<String> ) -> Config { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, Some("never") => ColorConfig::NeverColor, - Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x), + Some(x) => panic!( + "argument for --color must be auto, always, or never, but found `{}`", + x + ), }; Config { @@ -170,7 +286,11 @@ pub fn parse_config(args: Vec<String> ) -> Config { src_base: opt_path(matches, "src-base"), build_base: opt_path(matches, "build-base"), stage_id: matches.opt_str("stage-id").unwrap(), - mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"), + mode: matches + .opt_str("mode") + .unwrap() + .parse() + .expect("invalid mode"), run_ignored: matches.opt_present("ignored"), filter: matches.free.first().cloned(), filter_exact: matches.opt_present("exact"), @@ -189,10 +309,9 @@ pub fn parse_config(args: Vec<String> ) -> Config { android_cross_path: opt_path(matches, "android-cross-path"), adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), - adb_device_status: - opt_str2(matches.opt_str("target")).contains("android") && - "(none)" != opt_str2(matches.opt_str("adb-test-dir")) && - !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), + adb_device_status: opt_str2(matches.opt_str("target")).contains("android") + && "(none)" != opt_str2(matches.opt_str("adb-test-dir")) + && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), lldb_python_dir: matches.opt_str("lldb-python-dir"), verbose: matches.opt_present("verbose"), quiet: matches.opt_present("quiet"), @@ -213,7 +332,10 @@ pub fn parse_config(args: Vec<String> ) -> Config { pub fn log_config(config: &Config) { let c = config; logv(c, "configuration:".to_string()); - logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); + logv( + c, + format!("compile_lib_path: {:?}", config.compile_lib_path), + ); logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); @@ -222,24 +344,38 @@ pub fn log_config(config: &Config) { logv(c, format!("stage_id: {}", config.stage_id)); logv(c, format!("mode: {}", config.mode)); logv(c, format!("run_ignored: {}", config.run_ignored)); - logv(c, format!("filter: {}", - opt_str(&config.filter - .as_ref() - .map(|re| re.to_owned())))); + logv( + c, + format!( + "filter: {}", + opt_str(&config.filter.as_ref().map(|re| re.to_owned())) + ), + ); logv(c, format!("filter_exact: {}", config.filter_exact)); logv(c, format!("runtool: {}", opt_str(&config.runtool))); - logv(c, format!("host-rustcflags: {}", - opt_str(&config.host_rustcflags))); - logv(c, format!("target-rustcflags: {}", - opt_str(&config.target_rustcflags))); + logv( + c, + format!("host-rustcflags: {}", opt_str(&config.host_rustcflags)), + ); + logv( + c, + format!("target-rustcflags: {}", opt_str(&config.target_rustcflags)), + ); logv(c, format!("target: {}", config.target)); logv(c, format!("host: {}", config.host)); - logv(c, format!("android-cross-path: {:?}", - config.android_cross_path.display())); + logv( + c, + format!( + "android-cross-path: {:?}", + config.android_cross_path.display() + ), + ); logv(c, format!("adb_path: {:?}", config.adb_path)); logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir)); - logv(c, format!("adb_device_status: {}", - config.adb_device_status)); + logv( + c, + format!("adb_device_status: {}", config.adb_device_status), + ); logv(c, format!("ar: {}", config.ar)); logv(c, format!("linker: {:?}", config.linker)); logv(c, format!("verbose: {}", config.verbose)); @@ -264,8 +400,11 @@ pub fn opt_str2(maybestr: Option<String>) -> String { pub fn run_tests(config: &Config) { if config.target.contains("android") { if let DebugInfoGdb = config.mode { - println!("{} debug-info test uses tcp 5039 port.\ - please reserve it", config.target); + println!( + "{} debug-info test uses tcp 5039 port.\ + please reserve it", + config.target + ); // android debug-info test uses remote debugger so, we test 1 thread // at once as they're all sharing the same TCP port to communicate @@ -281,12 +420,14 @@ pub fn run_tests(config: &Config) { DebugInfoLldb => { if let Some(lldb_version) = config.lldb_version.as_ref() { if is_blacklisted_lldb_version(&lldb_version[..]) { - println!("WARNING: The used version of LLDB ({}) has a \ - known issue that breaks debuginfo tests. See \ - issue #32520 for more information. Skipping all \ - LLDB-based tests!", - lldb_version); - return + println!( + "WARNING: The used version of LLDB ({}) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + lldb_version + ); + return; } } @@ -297,11 +438,12 @@ pub fn run_tests(config: &Config) { } DebugInfoGdb => { - if config.remote_test_client.is_some() && - !config.target.contains("android"){ - println!("WARNING: debuginfo tests are not available when \ - testing with remote"); - return + if config.remote_test_client.is_some() && !config.target.contains("android") { + println!( + "WARNING: debuginfo tests are not available when \ + testing with remote" + ); + return; } } _ => { /* proceed */ } @@ -317,7 +459,9 @@ pub fn run_tests(config: &Config) { // sadly osx needs some file descriptor limits raised for running tests in // parallel (especially when we have lots and lots of child processes). // For context, see #8904 - unsafe { raise_fd_limit::raise_fd_limit(); } + unsafe { + raise_fd_limit::raise_fd_limit(); + } // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary env::set_var("__COMPAT_LAYER", "RunAsInvoker"); @@ -346,7 +490,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { bench_benchmarks: true, nocapture: match env::var("RUST_TEST_NOCAPTURE") { Ok(val) => &val != "0", - Err(_) => false + Err(_) => false, }, color: config.color, test_threads: None, @@ -357,24 +501,25 @@ pub fn test_opts(config: &Config) -> test::TestOpts { } pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> { - debug!("making tests from {:?}", - config.src_base.display()); + debug!("making tests from {:?}", config.src_base.display()); let mut tests = Vec::new(); - collect_tests_from_dir(config, - &config.src_base, - &config.src_base, - &PathBuf::new(), - &mut tests) - .unwrap(); + collect_tests_from_dir( + config, + &config.src_base, + &config.src_base, + &PathBuf::new(), + &mut tests, + ).unwrap(); tests } -fn collect_tests_from_dir(config: &Config, - base: &Path, - dir: &Path, - relative_dir_path: &Path, - tests: &mut Vec<test::TestDescAndFn>) - -> io::Result<()> { +fn collect_tests_from_dir( + config: &Config, + base: &Path, + dir: &Path, + relative_dir_path: &Path, + tests: &mut Vec<test::TestDescAndFn>, +) -> io::Result<()> { // Ignore directories that contain a file // `compiletest-ignore-dir`. for file in fs::read_dir(dir)? { @@ -390,7 +535,7 @@ fn collect_tests_from_dir(config: &Config, relative_dir: relative_dir_path.parent().unwrap().to_path_buf(), }; tests.push(make_test(config, &paths)); - return Ok(()) + return Ok(()); } } @@ -430,11 +575,7 @@ fn collect_tests_from_dir(config: &Config, fs::create_dir_all(&build_dir).unwrap(); } else { debug!("found directory: {:?}", file_path.display()); - collect_tests_from_dir(config, - base, - &file_path, - &relative_file_path, - tests)?; + collect_tests_from_dir(config, base, &file_path, &relative_file_path, tests)?; } } else { debug!("found other file/directory: {:?}", file_path.display()); @@ -467,13 +608,13 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn test::ShouldPanic::Yes } else { test::ShouldPanic::No - } + }, }; // Debugging emscripten code doesn't make sense today - let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) || - (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) && - config.target.contains("emscripten"); + let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) + || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) + && config.target.contains("emscripten"); test::TestDescAndFn { desc: test::TestDesc { @@ -487,28 +628,32 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn } fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { - let stamp_name = format!("{}-{}.stamp", - testpaths.file.file_name().unwrap() - .to_str().unwrap(), - config.stage_id); - config.build_base.canonicalize() - .unwrap_or_else(|_| config.build_base.clone()) - .join(&testpaths.relative_dir) - .join(stamp_name) + let stamp_name = format!( + "{}-{}.stamp", + testpaths.file.file_name().unwrap().to_str().unwrap(), + config.stage_id + ); + config + .build_base + .canonicalize() + .unwrap_or_else(|_| config.build_base.clone()) + .join(&testpaths.relative_dir) + .join(stamp_name) } fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> bool { - let rust_src_dir = config.find_rust_src_root().expect( - "Could not find Rust source root", - ); + let rust_src_dir = config + .find_rust_src_root() + .expect("Could not find Rust source root"); let stamp = mtime(&stamp(config, testpaths)); let mut inputs = vec![mtime(&testpaths.file), mtime(&config.rustc_path)]; for aux in props.aux.iter() { - inputs.push(mtime( - &testpaths.file.parent().unwrap().join("auxiliary").join( - aux, - ), - )); + inputs.push(mtime(&testpaths + .file + .parent() + .unwrap() + .join("auxiliary") + .join(aux))); } // Relevant pretty printer files let pretty_printer_files = [ @@ -529,21 +674,34 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo inputs.push(mtime(&rustdoc_path)); inputs.push(mtime(&rust_src_dir.join("src/etc/htmldocck.py"))); } + + // UI test files. + for extension in UI_EXTENSIONS { + for revision in &props.revisions { + let path = &expected_output_path(testpaths, Some(revision), extension); + inputs.push(mtime(path)); + } + + if props.revisions.is_empty() { + let path = &expected_output_path(testpaths, None, extension); + inputs.push(mtime(path)); + } + } + inputs.iter().any(|input| *input > stamp) } fn mtime(path: &Path) -> FileTime { - fs::metadata(path).map(|f| { - FileTime::from_last_modification_time(&f) - }).unwrap_or_else(|_| FileTime::zero()) + fs::metadata(path) + .map(|f| FileTime::from_last_modification_time(&f)) + .unwrap_or_else(|_| FileTime::zero()) } pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName { // Convert a complete path to something like // // run-pass/foo/bar/baz.rs - let path = - PathBuf::from(config.src_base.file_name().unwrap()) + let path = PathBuf::from(config.src_base.file_name().unwrap()) .join(&testpaths.relative_dir) .join(&testpaths.file.file_name().unwrap()); test::DynTestName(format!("[{}] {}", config.mode, path.display())) @@ -552,9 +710,7 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn { let config = config.clone(); let testpaths = testpaths.clone(); - test::DynTestFn(Box::new(move |()| { - runtest::run(config, &testpaths) - })) + test::DynTestFn(Box::new(move |()| runtest::run(config, &testpaths))) } /// Returns (Path to GDB, GDB Version, GDB has Rust Support) @@ -572,9 +728,17 @@ fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) { Some(ref s) => s, }; - let version_line = Command::new(gdb).arg("--version").output().map(|output| { - String::from_utf8_lossy(&output.stdout).lines().next().unwrap().to_string() - }).ok(); + let version_line = Command::new(gdb) + .arg("--version") + .output() + .map(|output| { + String::from_utf8_lossy(&output.stdout) + .lines() + .next() + .unwrap() + .to_string() + }) + .ok(); let version = match version_line { Some(line) => extract_gdb_version(&line), @@ -600,7 +764,7 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> { for (pos, c) in full_version_line.char_indices() { if prev_was_digit || !c.is_digit(10) { prev_was_digit = c.is_digit(10); - continue + continue; } prev_was_digit = true; @@ -623,10 +787,15 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> { Some(idx) => if line.as_bytes()[idx] == b'.' { let patch = &line[idx + 1..]; - let patch_len = patch.find(|c: char| !c.is_digit(10)) - .unwrap_or_else(|| patch.len()); + let patch_len = patch + .find(|c: char| !c.is_digit(10)) + .unwrap_or_else(|| patch.len()); let patch = &patch[..patch_len]; - let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; + let patch = if patch_len > 3 || patch_len == 0 { + None + } else { + Some(patch) + }; (&line[..idx], patch) } else { @@ -666,21 +835,36 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> { let full_version_line = full_version_line.trim(); for (pos, l) in full_version_line.char_indices() { - if l != 'l' && l != 'L' { continue } - if pos + 5 >= full_version_line.len() { continue } + if l != 'l' && l != 'L' { + continue; + } + if pos + 5 >= full_version_line.len() { + continue; + } let l = full_version_line[pos + 1..].chars().next().unwrap(); - if l != 'l' && l != 'L' { continue } + if l != 'l' && l != 'L' { + continue; + } let d = full_version_line[pos + 2..].chars().next().unwrap(); - if d != 'd' && d != 'D' { continue } + if d != 'd' && d != 'D' { + continue; + } let b = full_version_line[pos + 3..].chars().next().unwrap(); - if b != 'b' && b != 'B' { continue } + if b != 'b' && b != 'B' { + continue; + } let dash = full_version_line[pos + 4..].chars().next().unwrap(); - if dash != '-' { continue } + if dash != '-' { + continue; + } - let vers = full_version_line[pos + 5..].chars().take_while(|c| { - c.is_digit(10) - }).collect::<String>(); - if !vers.is_empty() { return Some(vers) } + let vers = full_version_line[pos + 5..] + .chars() + .take_while(|c| c.is_digit(10)) + .collect::<String>(); + if !vers.is_empty() { + return Some(vers); + } } } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7d20bb74c7a..a18f4ec1aad 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -10,10 +10,11 @@ use common::Config; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; -use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits}; -use common::{Incremental, RunMake, Ui, MirOpt}; +use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use common::{Incremental, MirOpt, RunMake, Ui}; +use common::{expected_output_path, UI_STDERR, UI_STDOUT}; use diff; -use errors::{self, ErrorKind, Error}; +use errors::{self, Error, ErrorKind}; use filetime::FileTime; use json; use header::TestProps; @@ -24,12 +25,12 @@ use std::collections::HashMap; use std::collections::HashSet; use std::env; use std::ffi::OsString; -use std::fs::{self, File, create_dir_all}; +use std::fs::{self, create_dir_all, File}; use std::fmt; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; -use std::process::{Command, Output, ExitStatus, Stdio, Child}; +use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; use extract_gdb_version; @@ -49,7 +50,6 @@ pub fn dylib_env_var() -> &'static str { pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { - "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => { if !config.adb_device_status { panic!("android device not available"); @@ -71,24 +71,24 @@ pub fn run(config: Config, testpaths: &TestPaths) { debug!("running {:?}", testpaths.file.display()); let base_props = TestProps::from_file(&testpaths.file, None, &config); - let base_cx = TestCx { config: &config, - props: &base_props, - testpaths, - revision: None }; + let base_cx = TestCx { + config: &config, + props: &base_props, + testpaths, + revision: None, + }; base_cx.init_all(); if base_props.revisions.is_empty() { base_cx.run_revision() } else { for revision in &base_props.revisions { - let revision_props = TestProps::from_file(&testpaths.file, - Some(revision), - &config); + let revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config); let rev_cx = TestCx { config: &config, props: &revision_props, testpaths, - revision: Some(revision) + revision: Some(revision), }; rev_cx.run_revision(); } @@ -103,7 +103,7 @@ struct TestCx<'test> { config: &'test Config, props: &'test TestProps, testpaths: &'test TestPaths, - revision: Option<&'test str> + revision: Option<&'test str>, } struct DebuggerCommands { @@ -125,8 +125,7 @@ impl<'test> TestCx<'test> { /// revisions, exactly once, with revision == None). fn run_revision(&self) { match self.config.mode { - CompileFail | - ParseFail => self.run_cfail_test(), + CompileFail | ParseFail => self.run_cfail_test(), RunFail => self.run_rfail_test(), RunPass => self.run_rpass_test(), RunPassValgrind => self.run_valgrind_test(), @@ -153,15 +152,14 @@ impl<'test> TestCx<'test> { if self.props.must_compile_successfully { if !proc_res.status.success() { - self.fatal_proc_rec( - "test compilation failed although it shouldn't!", - &proc_res); + self.fatal_proc_rec("test compilation failed although it shouldn't!", &proc_res); } } else { if proc_res.status.success() { self.fatal_proc_rec( &format!("{} test compiled successfully!", self.config.mode)[..], - &proc_res); + &proc_res, + ); } self.check_correct_failure_status(&proc_res); @@ -215,9 +213,9 @@ impl<'test> TestCx<'test> { const RUST_ERR: i32 = 101; if proc_res.status.code() != Some(RUST_ERR) { self.fatal_proc_rec( - &format!("failure produced the wrong error: {}", - proc_res.status), - proc_res); + &format!("failure produced the wrong error: {}", proc_res.status), + proc_res, + ); } } @@ -230,8 +228,10 @@ impl<'test> TestCx<'test> { // FIXME(#41968): Move this check to tidy? let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - assert!(expected_errors.is_empty(), - "run-pass tests with expected warnings should be moved to ui/"); + assert!( + expected_errors.is_empty(), + "run-pass tests with expected warnings should be moved to ui/" + ); let proc_res = self.exec_compiled_test(); @@ -256,7 +256,10 @@ impl<'test> TestCx<'test> { let mut new_config = self.config.clone(); new_config.runtool = new_config.valgrind_path.clone(); - let new_cx = TestCx { config: &new_config, ..*self }; + let new_cx = TestCx { + config: &new_config, + ..*self + }; proc_res = new_cx.exec_compiled_test(); if !proc_res.status.success() { @@ -268,28 +271,48 @@ impl<'test> TestCx<'test> { if self.props.pp_exact.is_some() { logv(self.config, "testing for exact pretty-printing".to_owned()); } else { - logv(self.config, "testing for converging pretty-printing".to_owned()); + logv( + self.config, + "testing for converging pretty-printing".to_owned(), + ); } - let rounds = match self.props.pp_exact { Some(_) => 1, None => 2 }; + let rounds = match self.props.pp_exact { + Some(_) => 1, + None => 2, + }; let mut src = String::new(); - File::open(&self.testpaths.file).unwrap().read_to_string(&mut src).unwrap(); + File::open(&self.testpaths.file) + .unwrap() + .read_to_string(&mut src) + .unwrap(); let mut srcs = vec![src]; let mut round = 0; while round < rounds { - logv(self.config, format!("pretty-printing round {} revision {:?}", - round, self.revision)); + logv( + self.config, + format!( + "pretty-printing round {} revision {:?}", + round, + self.revision + ), + ); let proc_res = self.print_source(srcs[round].to_owned(), &self.props.pretty_mode); if !proc_res.status.success() { - self.fatal_proc_rec(&format!("pretty-printing failed in round {} revision {:?}", - round, self.revision), - &proc_res); + self.fatal_proc_rec( + &format!( + "pretty-printing failed in round {} revision {:?}", + round, + self.revision + ), + &proc_res, + ); } - let ProcRes{ stdout, .. } = proc_res; + let ProcRes { stdout, .. } = proc_res; srcs.push(stdout); round += 1; } @@ -298,10 +321,13 @@ impl<'test> TestCx<'test> { Some(ref file) => { let filepath = self.testpaths.file.parent().unwrap().join(file); let mut s = String::new(); - File::open(&filepath).unwrap().read_to_string(&mut s).unwrap(); + File::open(&filepath) + .unwrap() + .read_to_string(&mut s) + .unwrap(); s } - None => { srcs[srcs.len() - 2].clone() } + None => srcs[srcs.len() - 2].clone(), }; let mut actual = srcs[srcs.len() - 1].clone(); @@ -315,7 +341,9 @@ impl<'test> TestCx<'test> { self.compare_source(&expected, &actual); // If we're only making sure that the output matches then just stop here - if self.props.pretty_compare_only { return; } + if self.props.pretty_compare_only { + return; + } // Finally, let's make sure it actually appears to remain valid code let proc_res = self.typecheck_source(actual); @@ -323,7 +351,9 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("pretty-printed source does not typecheck", &proc_res); } - if !self.props.pretty_expanded { return } + if !self.props.pretty_expanded { + return; + } // additionally, run `--pretty expanded` and try to build it. let proc_res = self.print_source(srcs[round].clone(), "expanded"); @@ -331,12 +361,16 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res); } - let ProcRes{ stdout: expanded_src, .. } = proc_res; + let ProcRes { + stdout: expanded_src, + .. + } = proc_res; let proc_res = self.typecheck_source(expanded_src); if !proc_res.status.success() { self.fatal_proc_rec( "pretty-printed source (expanded) does not typecheck", - &proc_res); + &proc_res, + ); } } @@ -344,37 +378,42 @@ impl<'test> TestCx<'test> { let aux_dir = self.aux_output_dir_name(); let mut rustc = Command::new(&self.config.rustc_path); - rustc.arg("-") + rustc + .arg("-") .arg("-Zunstable-options") .args(&["--unpretty", &pretty_type]) .args(&["--target", &self.config.target]) - .arg("-L").arg(&aux_dir) + .arg("-L") + .arg(&aux_dir) .args(self.split_maybe_args(&self.config.target_rustcflags)) .args(&self.props.compile_flags) .envs(self.props.exec_env.clone()); - self.compose_and_run(rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - Some(src)) + self.compose_and_run( + rustc, + self.config.compile_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + Some(src), + ) } - fn compare_source(&self, - expected: &str, - actual: &str) { + fn compare_source(&self, expected: &str, actual: &str) { if expected != actual { self.error("pretty-printed source does not match expected source"); - println!("\n\ -expected:\n\ -------------------------------------------\n\ -{}\n\ -------------------------------------------\n\ -actual:\n\ -------------------------------------------\n\ -{}\n\ -------------------------------------------\n\ -\n", - expected, actual); + println!( + "\n\ + expected:\n\ + ------------------------------------------\n\ + {}\n\ + ------------------------------------------\n\ + actual:\n\ + ------------------------------------------\n\ + {}\n\ + ------------------------------------------\n\ + \n", + expected, + actual + ); panic!(); } } @@ -394,12 +433,16 @@ actual:\n\ let aux_dir = self.aux_output_dir_name(); - rustc.arg("-") + rustc + .arg("-") .arg("-Zno-trans") - .arg("--out-dir").arg(&out_dir) + .arg("--out-dir") + .arg(&out_dir) .arg(&format!("--target={}", target)) - .arg("-L").arg(&self.config.build_base) - .arg("-L").arg(aux_dir); + .arg("-L") + .arg(&self.config.build_base) + .arg("-L") + .arg(aux_dir); if let Some(revision) = self.revision { rustc.args(&["--cfg", revision]); @@ -417,7 +460,7 @@ actual:\n\ let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), - .. self.config.clone() + ..self.config.clone() }; let test_cx = TestCx { @@ -444,7 +487,7 @@ actual:\n\ let DebuggerCommands { commands, check_lines, - breakpoint_lines + breakpoint_lines, } = self.parse_debugger_commands(prefixes); let mut cmds = commands.join("\n"); @@ -458,15 +501,12 @@ actual:\n\ let debugger_run_result; match &*self.config.target { - "arm-linux-androideabi" | - "armv7-linux-androideabi" | - "aarch64-linux-android" => { - + "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => { cmds = cmds.replace("run", "continue"); let tool_path = match self.config.android_cross_path.to_str() { Some(x) => x.to_owned(), - None => self.fatal("cannot find android cross path") + None => self.fatal("cannot find android cross path"), }; // write debugger script @@ -475,15 +515,20 @@ actual:\n\ script_str.push_str(&format!("set sysroot {}\n", tool_path)); script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap())); script_str.push_str("target remote :5039\n"); - script_str.push_str(&format!("set solib-search-path \ - ./{}/stage2/lib/rustlib/{}/lib/\n", - self.config.host, self.config.target)); + script_str.push_str(&format!( + "set solib-search-path \ + ./{}/stage2/lib/rustlib/{}/lib/\n", + self.config.host, + self.config.target + )); for line in &breakpoint_lines { - script_str.push_str(&format!("break {:?}:{}\n", - self.testpaths.file.file_name() - .unwrap() - .to_string_lossy(), - *line)[..]); + script_str.push_str( + &format!( + "break {:?}:{}\n", + self.testpaths.file.file_name().unwrap().to_string_lossy(), + *line + )[..], + ); } script_str.push_str(&cmds); script_str.push_str("\nquit\n"); @@ -505,14 +550,18 @@ actual:\n\ .status() .expect(&format!("failed to exec `{:?}`", adb_path)); - let adb_arg = format!("export LD_LIBRARY_PATH={}; \ - gdbserver{} :5039 {}/{}", - self.config.adb_test_dir.clone(), - if self.config.target.contains("aarch64") - {"64"} else {""}, - self.config.adb_test_dir.clone(), - exe_file.file_name().unwrap().to_str() - .unwrap()); + let adb_arg = format!( + "export LD_LIBRARY_PATH={}; \ + gdbserver{} :5039 {}/{}", + self.config.adb_test_dir.clone(), + if self.config.target.contains("aarch64") { + "64" + } else { + "" + }, + self.config.adb_test_dir.clone(), + exe_file.file_name().unwrap().to_str().unwrap() + ); debug!("adb arg: {}", adb_arg); let mut adb = Command::new(adb_path) @@ -531,25 +580,26 @@ actual:\n\ line.truncate(0); stdout.read_line(&mut line).unwrap(); if line.starts_with("Listening on port 5039") { - break + break; } } drop(stdout); let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths - let debugger_opts = - vec!["-quiet".to_owned(), - "-batch".to_owned(), - "-nx".to_owned(), - format!("-command={}", debugger_script.to_str().unwrap())]; + let debugger_opts = vec![ + "-quiet".to_owned(), + "-batch".to_owned(), + "-nx".to_owned(), + format!("-command={}", debugger_script.to_str().unwrap()), + ]; let mut gdb_path = tool_path; gdb_path.push_str("/bin/gdb"); let Output { status, stdout, - stderr + stderr, } = Command::new(&gdb_path) .args(&debugger_opts) .output() @@ -574,14 +624,15 @@ actual:\n\ } _ => { - let rust_src_root = self.config.find_rust_src_root().expect( - "Could not find Rust source root", - ); + let rust_src_root = self.config + .find_rust_src_root() + .expect("Could not find Rust source root"); let rust_pp_module_rel_path = Path::new("./src/etc"); - let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) - .to_str() - .unwrap() - .to_owned(); + let rust_pp_module_abs_path = rust_src_root + .join(rust_pp_module_rel_path) + .to_str() + .unwrap() + .to_owned(); // write debugger script let mut script_str = String::with_capacity(2048); script_str.push_str(&format!("set charset {}\n", Self::charset())); @@ -589,21 +640,25 @@ actual:\n\ match self.config.gdb_version { Some(version) => { - println!("NOTE: compiletest thinks it is using GDB version {}", - version); + println!( + "NOTE: compiletest thinks it is using GDB version {}", + version + ); if version > extract_gdb_version("7.4").unwrap() { // Add the directory containing the pretty printers to // GDB's script auto loading safe path - script_str.push_str( - &format!("add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace(r"\", r"\\")) - ); + script_str.push_str(&format!( + "add-auto-load-safe-path {}\n", + rust_pp_module_abs_path.replace(r"\", r"\\") + )); } } _ => { - println!("NOTE: compiletest does not know which version of \ - GDB it is using"); + println!( + "NOTE: compiletest does not know which version of \ + GDB it is using" + ); } } @@ -612,13 +667,13 @@ actual:\n\ script_str.push_str("set print pretty off\n"); // Add the pretty printer directory to GDB's source-file search path - script_str.push_str(&format!("directory {}\n", - rust_pp_module_abs_path)); + script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path)); // Load the target executable - script_str.push_str(&format!("file {}\n", - exe_file.to_str().unwrap() - .replace(r"\", r"\\"))); + script_str.push_str(&format!( + "file {}\n", + exe_file.to_str().unwrap().replace(r"\", r"\\") + )); // Force GDB to print values in the Rust format. if self.config.gdb_native_rust { @@ -627,10 +682,11 @@ actual:\n\ // Add line breakpoints for line in &breakpoint_lines { - script_str.push_str(&format!("break '{}':{}\n", - self.testpaths.file.file_name().unwrap() - .to_string_lossy(), - *line)); + script_str.push_str(&format!( + "break '{}':{}\n", + self.testpaths.file.file_name().unwrap().to_string_lossy(), + *line + )); } script_str.push_str(&cmds); @@ -642,21 +698,23 @@ actual:\n\ let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths - let debugger_opts = - vec!["-quiet".to_owned(), - "-batch".to_owned(), - "-nx".to_owned(), - format!("-command={}", debugger_script.to_str().unwrap())]; + let debugger_opts = vec![ + "-quiet".to_owned(), + "-batch".to_owned(), + "-nx".to_owned(), + format!("-command={}", debugger_script.to_str().unwrap()), + ]; let mut gdb = Command::new(self.config.gdb.as_ref().unwrap()); gdb.args(&debugger_opts) .env("PYTHONPATH", rust_pp_module_abs_path); - debugger_run_result = - self.compose_and_run(gdb, - self.config.run_lib_path.to_str().unwrap(), - None, - None); + debugger_run_result = self.compose_and_run( + gdb, + self.config.run_lib_path.to_str().unwrap(), + None, + None, + ); } } @@ -677,7 +735,7 @@ actual:\n\ let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), - .. self.config.clone() + ..self.config.clone() }; @@ -700,12 +758,16 @@ actual:\n\ match self.config.lldb_version { Some(ref version) => { - println!("NOTE: compiletest thinks it is using LLDB version {}", - version); + println!( + "NOTE: compiletest thinks it is using LLDB version {}", + version + ); } _ => { - println!("NOTE: compiletest does not know which version of \ - LLDB it is using"); + println!( + "NOTE: compiletest does not know which version of \ + LLDB it is using" + ); } } @@ -725,17 +787,18 @@ actual:\n\ script_str.push_str("version\n"); // Switch LLDB into "Rust mode" - let rust_src_root = self.config.find_rust_src_root().expect( - "Could not find Rust source root", - ); + let rust_src_root = self.config + .find_rust_src_root() + .expect("Could not find Rust source root"); let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py"); - let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) - .to_str() - .unwrap() - .to_owned(); - - script_str.push_str(&format!("command script import {}\n", - &rust_pp_module_abs_path[..])[..]); + let rust_pp_module_abs_path = rust_src_root + .join(rust_pp_module_rel_path) + .to_str() + .unwrap() + .to_owned(); + + script_str + .push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[..]); script_str.push_str("type summary add --no-value "); script_str.push_str("--python-function lldb_rust_formatters.print_val "); script_str.push_str("-x \".*\" --category Rust\n"); @@ -744,9 +807,11 @@ actual:\n\ // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); for line in &breakpoint_lines { - script_str.push_str(&format!("breakpoint set --file '{}' --line {}\n", - source_file_name, - line)); + script_str.push_str(&format!( + "breakpoint set --file '{}' --line {}\n", + source_file_name, + line + )); } // Append the other commands @@ -764,9 +829,7 @@ actual:\n\ let debugger_script = self.make_out_name("debugger.script"); // Let LLDB execute the script via lldb_batchmode.py - let debugger_run_result = self.run_lldb(&exe_file, - &debugger_script, - &rust_src_root); + let debugger_run_result = self.run_lldb(&exe_file, &debugger_script, &rust_src_root); if !debugger_run_result.status.success() { self.fatal_proc_rec("Error while running LLDB", &debugger_run_result); @@ -775,32 +838,39 @@ actual:\n\ self.check_debugger_output(&debugger_run_result, &check_lines); } - fn run_lldb(&self, - test_executable: &Path, - debugger_script: &Path, - rust_src_root: &Path) - -> ProcRes { + fn run_lldb( + &self, + test_executable: &Path, + debugger_script: &Path, + rust_src_root: &Path, + ) -> ProcRes { // Prepare the lldb_batchmode which executes the debugger script let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py"); - self.cmd2procres(Command::new(&self.config.lldb_python) - .arg(&lldb_script_path) - .arg(test_executable) - .arg(debugger_script) - .env("PYTHONPATH", - self.config.lldb_python_dir.as_ref().unwrap())) + self.cmd2procres( + Command::new(&self.config.lldb_python) + .arg(&lldb_script_path) + .arg(test_executable) + .arg(debugger_script) + .env("PYTHONPATH", self.config.lldb_python_dir.as_ref().unwrap()), + ) } fn cmd2procres(&self, cmd: &mut Command) -> ProcRes { let (status, out, err) = match cmd.output() { - Ok(Output { status, stdout, stderr }) => { - (status, - String::from_utf8(stdout).unwrap(), - String::from_utf8(stderr).unwrap()) - }, - Err(e) => { - self.fatal(&format!("Failed to setup Python process for \ - LLDB script: {}", e)) - } + Ok(Output { + status, + stdout, + stderr, + }) => ( + status, + String::from_utf8(stdout).unwrap(), + String::from_utf8(stderr).unwrap(), + ), + Err(e) => self.fatal(&format!( + "Failed to setup Python process for \ + LLDB script: {}", + e + )), }; self.dump_output(&out, &err); @@ -808,15 +878,17 @@ actual:\n\ status, stdout: out, stderr: err, - cmdline: format!("{:?}", cmd) + cmdline: format!("{:?}", cmd), } } fn parse_debugger_commands(&self, debugger_prefixes: &[&str]) -> DebuggerCommands { - let directives = debugger_prefixes.iter().map(|prefix| ( - format!("{}-command", prefix), - format!("{}-check", prefix), - )).collect::<Vec<_>>(); + let directives = debugger_prefixes + .iter() + .map(|prefix| { + (format!("{}-command", prefix), format!("{}-check", prefix)) + }) + .collect::<Vec<_>>(); let mut breakpoint_lines = vec![]; let mut commands = vec![]; @@ -831,22 +903,16 @@ actual:\n\ } for &(ref command_directive, ref check_directive) in &directives { - self.config.parse_name_value_directive( - &line, - command_directive).map(|cmd| { - commands.push(cmd) - }); - - self.config.parse_name_value_directive( - &line, - check_directive).map(|cmd| { - check_lines.push(cmd) - }); + self.config + .parse_name_value_directive(&line, command_directive) + .map(|cmd| commands.push(cmd)); + + self.config + .parse_name_value_directive(&line, check_directive) + .map(|cmd| check_lines.push(cmd)); } } - Err(e) => { - self.fatal(&format!("Error while parsing debugger commands: {}", e)) - } + Err(e) => self.fatal(&format!("Error while parsing debugger commands: {}", e)), } counter += 1; } @@ -864,15 +930,11 @@ actual:\n\ } // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS. - let options_to_remove = [ - "-O".to_owned(), - "-g".to_owned(), - "--debuginfo".to_owned() - ]; - let new_options = - self.split_maybe_args(options).into_iter() - .filter(|x| !options_to_remove.contains(x)) - .collect::<Vec<String>>(); + let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()]; + let new_options = self.split_maybe_args(options) + .into_iter() + .filter(|x| !options_to_remove.contains(x)) + .collect::<Vec<String>>(); Some(new_options.join(" ")) } @@ -891,9 +953,13 @@ actual:\n\ } } if check_line_index != num_check_lines && num_check_lines > 0 { - self.fatal_proc_rec(&format!("line not found in debugger output: {}", - check_lines[check_line_index]), - debugger_run_result); + self.fatal_proc_rec( + &format!( + "line not found in debugger output: {}", + check_lines[check_line_index] + ), + debugger_run_result, + ); } fn check_single_line(line: &str, check_line: &str) -> bool { @@ -904,17 +970,18 @@ actual:\n\ let can_start_anywhere = check_line.starts_with("[...]"); let can_end_anywhere = check_line.ends_with("[...]"); - let check_fragments: Vec<&str> = check_line.split("[...]") - .filter(|frag| !frag.is_empty()) - .collect(); + let check_fragments: Vec<&str> = check_line + .split("[...]") + .filter(|frag| !frag.is_empty()) + .collect(); if check_fragments.is_empty() { return true; } let (mut rest, first_fragment) = if can_start_anywhere { match line.find(check_fragments[0]) { - Some(pos) => (&line[pos + check_fragments[0].len() ..], 1), - None => return false + Some(pos) => (&line[pos + check_fragments[0].len()..], 1), + None => return false, } } else { (line, 0) @@ -923,9 +990,9 @@ actual:\n\ for current_fragment in &check_fragments[first_fragment..] { match rest.find(current_fragment) { Some(pos) => { - rest = &rest[pos + current_fragment.len() .. ]; + rest = &rest[pos + current_fragment.len()..]; } - None => return false + None => return false, } } @@ -937,15 +1004,15 @@ actual:\n\ } } - fn check_error_patterns(&self, - output_to_check: &str, - proc_res: &ProcRes) { + fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) { if self.props.error_patterns.is_empty() { if self.props.must_compile_successfully { - return + return; } else { - self.fatal(&format!("no error pattern specified in {:?}", - self.testpaths.file.display())); + self.fatal(&format!( + "no error pattern specified in {:?}", + self.testpaths.file.display() + )); } } let mut next_err_idx = 0; @@ -963,13 +1030,16 @@ actual:\n\ next_err_pat = self.props.error_patterns[next_err_idx].trim(); } } - if done { return; } + if done { + return; + } let missing_patterns = &self.props.error_patterns[next_err_idx..]; if missing_patterns.len() == 1 { self.fatal_proc_rec( &format!("error pattern '{}' not found!", missing_patterns[0]), - proc_res); + proc_res, + ); } else { for pattern in missing_patterns { self.error(&format!("error pattern '{}' not found!", *pattern)); @@ -986,9 +1056,7 @@ actual:\n\ } } - fn check_forbid_output(&self, - output_to_check: &str, - proc_res: &ProcRes) { + fn check_forbid_output(&self, output_to_check: &str, proc_res: &ProcRes) { for pat in &self.props.forbid_output { if output_to_check.contains(pat) { self.fatal_proc_rec("forbidden pattern found in compiler output", proc_res); @@ -996,41 +1064,42 @@ actual:\n\ } } - fn check_expected_errors(&self, - expected_errors: Vec<errors::Error>, - proc_res: &ProcRes) { - if proc_res.status.success() && - expected_errors.iter().any(|x| x.kind == Some(ErrorKind::Error)) { + fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &ProcRes) { + if proc_res.status.success() + && expected_errors + .iter() + .any(|x| x.kind == Some(ErrorKind::Error)) + { self.fatal_proc_rec("process did not return an error status", proc_res); } - let file_name = - format!("{}", self.testpaths.file.display()) - .replace(r"\", "/"); // on windows, translate all '\' path separators to '/' + // on windows, translate all '\' path separators to '/' + let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/"); // If the testcase being checked contains at least one expected "help" // message, then we'll ensure that all "help" messages are expected. // Otherwise, all "help" messages reported by the compiler will be ignored. // This logic also applies to "note" messages. - let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help)); - let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); + let expect_help = expected_errors + .iter() + .any(|ee| ee.kind == Some(ErrorKind::Help)); + let expect_note = expected_errors + .iter() + .any(|ee| ee.kind == Some(ErrorKind::Note)); // Parse the JSON output from the compiler and extract out the messages. let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res); let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; for actual_error in &actual_errors { - let opt_index = - expected_errors - .iter() - .enumerate() - .position(|(index, expected_error)| { - !found[index] && - actual_error.line_num == expected_error.line_num && - (expected_error.kind.is_none() || - actual_error.kind == expected_error.kind) && - actual_error.msg.contains(&expected_error.msg) - }); + let opt_index = expected_errors.iter().enumerate().position( + |(index, expected_error)| { + !found[index] && actual_error.line_num == expected_error.line_num + && (expected_error.kind.is_none() + || actual_error.kind == expected_error.kind) + && actual_error.msg.contains(&expected_error.msg) + }, + ); match opt_index { Some(index) => { @@ -1041,14 +1110,16 @@ actual:\n\ None => { if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) { - self.error( - &format!("{}:{}: unexpected {}: '{}'", - file_name, - actual_error.line_num, - actual_error.kind.as_ref() - .map_or(String::from("message"), - |k| k.to_string()), - actual_error.msg)); + self.error(&format!( + "{}:{}: unexpected {}: '{}'", + file_name, + actual_error.line_num, + actual_error + .kind + .as_ref() + .map_or(String::from("message"), |k| k.to_string()), + actual_error.msg + )); unexpected.push(actual_error); } } @@ -1059,24 +1130,27 @@ actual:\n\ // anything not yet found is a problem for (index, expected_error) in expected_errors.iter().enumerate() { if !found[index] { - self.error( - &format!("{}:{}: expected {} not found: {}", - file_name, - expected_error.line_num, - expected_error.kind.as_ref() - .map_or("message".into(), - |k| k.to_string()), - expected_error.msg)); + self.error(&format!( + "{}:{}: expected {} not found: {}", + file_name, + expected_error.line_num, + expected_error + .kind + .as_ref() + .map_or("message".into(), |k| k.to_string()), + expected_error.msg + )); not_found.push(expected_error); } } if !unexpected.is_empty() || !not_found.is_empty() { - self.error( - &format!("{} unexpected errors found, {} expected errors not found", - unexpected.len(), not_found.len())); - println!("status: {}\ncommand: {}", - proc_res.status, proc_res.cmdline); + self.error(&format!( + "{} unexpected errors found, {} expected errors not found", + unexpected.len(), + not_found.len() + )); + println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline); if !unexpected.is_empty() { println!("unexpected errors (from JSON output): {:#?}\n", unexpected); } @@ -1091,24 +1165,25 @@ actual:\n\ /// which did not match any of the expected error. We always require /// errors/warnings to be explicitly listed, but only require /// helps/notes if there are explicit helps/notes given. - fn is_unexpected_compiler_message(&self, - actual_error: &Error, - expect_help: bool, - expect_note: bool) - -> bool { + fn is_unexpected_compiler_message( + &self, + actual_error: &Error, + expect_help: bool, + expect_note: bool, + ) -> bool { match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) | - Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) | - None => false + Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, + Some(ErrorKind::Suggestion) | None => false, } } fn compile_test(&self) -> ProcRes { let mut rustc = self.make_compile_args( - &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name())); + &self.testpaths.file, + TargetLocation::ThisFile(self.make_exe_name()), + ); rustc.arg("-L").arg(&self.aux_output_dir_name()); @@ -1131,14 +1206,14 @@ actual:\n\ if self.props.build_aux_docs { for rel_ab in &self.props.aux_builds { let aux_testpaths = self.compute_aux_test_paths(rel_ab); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, - self.revision, - self.config); + let aux_props = + self.props + .from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { config: self.config, props: &aux_props, testpaths: &aux_testpaths, - revision: self.revision + revision: self.revision, }; let auxres = aux_cx.document(out_dir); if !auxres.status.success() { @@ -1149,15 +1224,25 @@ actual:\n\ let aux_dir = self.aux_output_dir_name(); - let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"); + let rustdoc_path = self.config + .rustdoc_path + .as_ref() + .expect("--rustdoc-path passed"); let mut rustdoc = Command::new(rustdoc_path); - rustdoc.arg("-L").arg(aux_dir) - .arg("-o").arg(out_dir) + rustdoc + .arg("-L") + .arg(aux_dir) + .arg("-o") + .arg(out_dir) .arg(&self.testpaths.file) .args(&self.props.compile_flags); if let Some(ref linker) = self.config.linker { - rustdoc.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); + rustdoc + .arg("--linker") + .arg(linker) + .arg("-Z") + .arg("unstable-options"); } self.compose_and_run_compiler(rustdoc, None) @@ -1187,34 +1272,39 @@ actual:\n\ for entry in entries { let entry = entry.unwrap(); if !entry.path().is_file() { - continue + continue; } prog.push_str(":"); prog.push_str(entry.path().to_str().unwrap()); } } - let mut test_client = Command::new( - self.config.remote_test_client.as_ref().unwrap()); + let mut test_client = + Command::new(self.config.remote_test_client.as_ref().unwrap()); test_client .args(&["run", &prog]) .args(args) .envs(env.clone()); - self.compose_and_run(test_client, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - None) + self.compose_and_run( + test_client, + self.config.run_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + None, + ) } _ => { let aux_dir = self.aux_output_dir_name(); let ProcArgs { prog, args } = self.make_run_args(); let mut program = Command::new(&prog); - program.args(args) + program + .args(args) .current_dir(&self.output_base_name().parent().unwrap()) .envs(env.clone()); - self.compose_and_run(program, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - None) + self.compose_and_run( + program, + self.config.run_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + None, + ) } } } @@ -1222,24 +1312,29 @@ actual:\n\ /// For each `aux-build: foo/bar` annotation, we check to find the /// file in a `aux` directory relative to the test itself. fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths { - let test_ab = self.testpaths.file - .parent() - .expect("test file path has no parent") - .join("auxiliary") - .join(rel_ab); + let test_ab = self.testpaths + .file + .parent() + .expect("test file path has no parent") + .join("auxiliary") + .join(rel_ab); if !test_ab.exists() { - self.fatal(&format!("aux-build `{}` source not found", test_ab.display())) + self.fatal(&format!( + "aux-build `{}` source not found", + test_ab.display() + )) } TestPaths { file: test_ab, base: self.testpaths.base.clone(), - relative_dir: self.testpaths.relative_dir - .join("auxiliary") - .join(rel_ab) - .parent() - .expect("aux-build path has no parent") - .to_path_buf() + relative_dir: self.testpaths + .relative_dir + .join("auxiliary") + .join(rel_ab) + .parent() + .expect("aux-build path has no parent") + .to_path_buf(), } } @@ -1252,9 +1347,9 @@ actual:\n\ for rel_ab in &self.props.aux_builds { let aux_testpaths = self.compute_aux_test_paths(rel_ab); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, - self.revision, - self.config); + let aux_props = + self.props + .from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_output = { let f = self.make_lib_name(&self.testpaths.file); let parent = f.parent().unwrap(); @@ -1264,15 +1359,16 @@ actual:\n\ config: self.config, props: &aux_props, testpaths: &aux_testpaths, - revision: self.revision + revision: self.revision, }; let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); let crate_type = if aux_props.no_prefer_dynamic { None - } else if (self.config.target.contains("musl") && !aux_props.force_host) || - self.config.target.contains("wasm32") || - self.config.target.contains("emscripten") { + } else if (self.config.target.contains("musl") && !aux_props.force_host) + || self.config.target.contains("wasm32") + || self.config.target.contains("emscripten") + { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible // for the test suite (otherwise including libstd statically in all @@ -1293,32 +1389,40 @@ actual:\n\ aux_rustc.arg("-L").arg(&aux_dir); - let auxres = aux_cx.compose_and_run(aux_rustc, - aux_cx.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - None); + let auxres = aux_cx.compose_and_run( + aux_rustc, + aux_cx.config.compile_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + None, + ); if !auxres.status.success() { self.fatal_proc_rec( - &format!("auxiliary build of {:?} failed to compile: ", - aux_testpaths.file.display()), - &auxres); + &format!( + "auxiliary build of {:?} failed to compile: ", + aux_testpaths.file.display() + ), + &auxres, + ); } } rustc.envs(self.props.rustc_env.clone()); - self.compose_and_run(rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - input) - } - - fn compose_and_run(&self, - mut command: Command, - lib_path: &str, - aux_path: Option<&str>, - input: Option<String>) -> ProcRes { - let cmdline = - { + self.compose_and_run( + rustc, + self.config.compile_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + input, + ) + } + + fn compose_and_run( + &self, + mut command: Command, + lib_path: &str, + aux_path: Option<&str>, + input: Option<String>, + ) -> ProcRes { + let cmdline = { let cmdline = self.make_cmdline(&command, lib_path); logv(self.config, format!("executing {}", cmdline)); cmdline @@ -1342,13 +1446,23 @@ actual:\n\ let newpath = env::join_paths(&path).unwrap(); command.env(dylib_env_var(), newpath); - let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command)); + let mut child = command + .spawn() + .expect(&format!("failed to exec `{:?}`", &command)); if let Some(input) = input { - child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); + child + .stdin + .as_mut() + .unwrap() + .write_all(input.as_bytes()) + .unwrap(); } - let Output { status, stdout, stderr } = read2_abbreviated(child) - .expect("failed to read output"); + let Output { + status, + stdout, + stderr, + } = read2_abbreviated(child).expect("failed to read output"); let result = ProcRes { status, @@ -1364,11 +1478,11 @@ actual:\n\ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command { let mut rustc = Command::new(&self.config.rustc_path); - rustc.arg(input_file) - .arg("-L").arg(&self.config.build_base); + rustc.arg(input_file).arg("-L").arg(&self.config.build_base); // Optionally prevent default --target if specified in test compile-flags. - let custom_target = self.props.compile_flags + let custom_target = self.props + .compile_flags .iter() .any(|x| x.starts_with("--target")); @@ -1387,15 +1501,16 @@ actual:\n\ } if let Some(ref incremental_dir) = self.props.incremental_dir { - rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]); + rustc.args(&[ + "-Z", + &format!("incremental={}", incremental_dir.display()), + ]); rustc.args(&["-Z", "incremental-verify-ich"]); rustc.args(&["-Z", "incremental-queries"]); } match self.config.mode { - CompileFail | - ParseFail | - Incremental => { + CompileFail | ParseFail | Incremental => { // If we are extracting and matching errors in the new // fashion, then you want JSON mode. Old-skool error // patterns still match the raw compiler output. @@ -1403,16 +1518,19 @@ actual:\n\ rustc.args(&["--error-format", "json"]); } } - Ui => { - if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) { - rustc.args(&["--error-format", "json"]); - } - } + Ui => if !self.props + .compile_flags + .iter() + .any(|s| s.starts_with("--error-format")) + { + rustc.args(&["--error-format", "json"]); + }, MirOpt => { rustc.args(&[ "-Zdump-mir=all", "-Zmir-opt-level=3", - "-Zdump-mir-exclude-pass-number"]); + "-Zdump-mir-exclude-pass-number", + ]); let mir_dump_dir = self.get_mir_dump_dir(); let _ = fs::remove_dir_all(&mir_dump_dir); @@ -1532,26 +1650,21 @@ actual:\n\ args.extend(self.split_maybe_args(&self.props.run_flags)); let prog = args.remove(0); - ProcArgs { - prog, - args, - } + ProcArgs { prog, args } } fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> { match *argstr { - Some(ref s) => { - s - .split(' ') - .filter_map(|s| { - if s.chars().all(|c| c.is_whitespace()) { - None - } else { - Some(s.to_owned()) - } - }).collect() - } - None => Vec::new() + Some(ref s) => s.split(' ') + .filter_map(|s| { + if s.chars().all(|c| c.is_whitespace()) { + None + } else { + Some(s.to_owned()) + } + }) + .collect(), + None => Vec::new(), } } @@ -1565,7 +1678,11 @@ actual:\n\ // Build the LD_LIBRARY_PATH variable as it would be seen on the command line // for diagnostic purposes fn lib_path_cmd_prefix(path: &str) -> String { - format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) + format!( + "{}=\"{}\"", + util::lib_path_env_var(), + util::make_new_path(path) + ) } format!("{} {:?}", lib_path_cmd_prefix(libpath), command) @@ -1584,11 +1701,12 @@ actual:\n\ self.maybe_dump_to_stdout(out, err); } - fn dump_output_file(&self, - out: &str, - extension: &str) { + fn dump_output_file(&self, out: &str, extension: &str) { let outfile = self.make_out_name(extension); - File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap(); + File::create(&outfile) + .unwrap() + .write_all(out.as_bytes()) + .unwrap(); } fn make_out_name(&self, extension: &str) -> PathBuf { @@ -1613,8 +1731,7 @@ actual:\n\ let dir = self.config.build_base.join(&self.testpaths.relative_dir); // Note: The directory `dir` is created during `collect_tests_from_dir` - dir - .join(&self.output_testname(&self.testpaths.file)) + dir.join(&self.output_testname(&self.testpaths.file)) .with_extension(&self.config.stage_id) } @@ -1631,12 +1748,13 @@ actual:\n\ fn error(&self, err: &str) { match self.revision { Some(rev) => println!("\nerror in revision `{}`: {}", rev, err), - None => println!("\nerror: {}", err) + None => println!("\nerror: {}", err), } } fn fatal(&self, err: &str) -> ! { - self.error(err); panic!(); + self.error(err); + panic!(); } fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! { @@ -1652,10 +1770,10 @@ actual:\n\ // errors here. fn try_print_open_handles(&self) { if !cfg!(windows) { - return + return; } if self.config.mode != Incremental { - return + return; } let filename = match self.testpaths.file.file_stem() { @@ -1689,11 +1807,10 @@ actual:\n\ fn compile_test_and_save_ir(&self) -> ProcRes { let aux_dir = self.aux_output_dir_name(); - let output_file = TargetLocation::ThisDirectory( - self.output_base_name().parent().unwrap().to_path_buf()); + let output_file = + TargetLocation::ThisDirectory(self.output_base_name().parent().unwrap().to_path_buf()); let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); - rustc.arg("-L").arg(aux_dir) - .arg("--emit=llvm-ir"); + rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir"); self.compose_and_run_compiler(rustc, None) } @@ -1701,7 +1818,9 @@ actual:\n\ fn check_ir_with_filecheck(&self) -> ProcRes { let irfile = self.output_base_name().with_extension("ll"); let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap()); - filecheck.arg("--input-file").arg(irfile) + filecheck + .arg("--input-file") + .arg(irfile) .arg(&self.testpaths.file); self.compose_and_run(filecheck, "", None, None) } @@ -1763,105 +1882,119 @@ actual:\n\ } } - fn get_lines<P: AsRef<Path>>(&self, path: &P, - mut other_files: Option<&mut Vec<String>>) -> Vec<usize> { - let mut file = fs::File::open(path) - .expect("markdown_test_output_check_entry File::open failed"); + fn get_lines<P: AsRef<Path>>( + &self, + path: &P, + mut other_files: Option<&mut Vec<String>>, + ) -> Vec<usize> { + let mut file = + fs::File::open(path).expect("markdown_test_output_check_entry File::open failed"); let mut content = String::new(); file.read_to_string(&mut content) .expect("markdown_test_output_check_entry read_to_string failed"); let mut ignore = false; - content.lines() - .enumerate() - .filter_map(|(line_nb, line)| { - if (line.trim_left().starts_with("pub mod ") || - line.trim_left().starts_with("mod ")) && - line.ends_with(';') { - if let Some(ref mut other_files) = other_files { - other_files.push(line.rsplit("mod ") - .next() - .unwrap() - .replace(";", "")); - } - None - } else { - let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); - if line.starts_with("```") { - if ignore { - ignore = false; - None - } else { - ignore = true; - Some(line_nb + 1) - } - } else { - None - } - } - }) - .collect() + content + .lines() + .enumerate() + .filter_map(|(line_nb, line)| { + if (line.trim_left().starts_with("pub mod ") + || line.trim_left().starts_with("mod ")) + && line.ends_with(';') + { + if let Some(ref mut other_files) = other_files { + other_files.push(line.rsplit("mod ").next().unwrap().replace(";", "")); + } + None + } else { + let sline = line.split("///").last().unwrap_or(""); + let line = sline.trim_left(); + if line.starts_with("```") { + if ignore { + ignore = false; + None + } else { + ignore = true; + Some(line_nb + 1) + } + } else { + None + } + } + }) + .collect() } fn check_rustdoc_test_option(&self, res: ProcRes) { let mut other_files = Vec::new(); let mut files: HashMap<String, Vec<usize>> = HashMap::new(); let cwd = env::current_dir().unwrap(); - files.insert(self.testpaths.file.strip_prefix(&cwd) - .unwrap_or(&self.testpaths.file) - .to_str() - .unwrap() - .replace('\\', "/"), - self.get_lines(&self.testpaths.file, Some(&mut other_files))); + files.insert( + self.testpaths + .file + .strip_prefix(&cwd) + .unwrap_or(&self.testpaths.file) + .to_str() + .unwrap() + .replace('\\', "/"), + self.get_lines(&self.testpaths.file, Some(&mut other_files)), + ); for other_file in other_files { let mut path = self.testpaths.file.clone(); path.set_file_name(&format!("{}.rs", other_file)); - files.insert(path.strip_prefix(&cwd) - .unwrap_or(&path) - .to_str() - .unwrap() - .replace('\\', "/"), - self.get_lines(&path, None)); + files.insert( + path.strip_prefix(&cwd) + .unwrap_or(&path) + .to_str() + .unwrap() + .replace('\\', "/"), + self.get_lines(&path, None), + ); } let mut tested = 0; - for _ in res.stdout.split('\n') - .filter(|s| s.starts_with("test ")) - .inspect(|s| { - let tmp: Vec<&str> = s.split(" - ").collect(); - if tmp.len() == 2 { - let path = tmp[0].rsplit("test ").next().unwrap(); - if let Some(ref mut v) = files.get_mut( - &path.replace('\\', "/")) { - tested += 1; - let mut iter = tmp[1].split("(line "); - iter.next(); - let line = iter.next() - .unwrap_or(")") - .split(')') - .next() - .unwrap_or("0") - .parse() - .unwrap_or(0); - if let Ok(pos) = v.binary_search(&line) { - v.remove(pos); - } else { - self.fatal_proc_rec( - &format!("Not found doc test: \"{}\" in \"{}\":{:?}", - s, path, v), - &res); - } - } - } - }) {} + for _ in res.stdout + .split('\n') + .filter(|s| s.starts_with("test ")) + .inspect(|s| { + let tmp: Vec<&str> = s.split(" - ").collect(); + if tmp.len() == 2 { + let path = tmp[0].rsplit("test ").next().unwrap(); + if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) { + tested += 1; + let mut iter = tmp[1].split("(line "); + iter.next(); + let line = iter.next() + .unwrap_or(")") + .split(')') + .next() + .unwrap_or("0") + .parse() + .unwrap_or(0); + if let Ok(pos) = v.binary_search(&line) { + v.remove(pos); + } else { + self.fatal_proc_rec( + &format!("Not found doc test: \"{}\" in \"{}\":{:?}", s, path, v), + &res, + ); + } + } + } + }) {} if tested == 0 { self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res); } else { for (entry, v) in &files { if !v.is_empty() { - self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}", - if v.len() > 1 { "s" } else { "" }, entry, v), - &res); + self.fatal_proc_rec( + &format!( + "Not found test at line{} \"{}\":{:?}", + if v.len() > 1 { "s" } else { "" }, + entry, + v + ), + &res, + ); } } } @@ -1897,13 +2030,13 @@ actual:\n\ let mut wrong_cgus = Vec::new(); for expected_item in &expected { - let actual_item_with_same_name = actual.iter() - .find(|ti| ti.name == expected_item.name); + let actual_item_with_same_name = actual.iter().find(|ti| ti.name == expected_item.name); if let Some(actual_item) = actual_item_with_same_name { if !expected_item.codegen_units.is_empty() && // Also check for codegen units - expected_item.codegen_units != actual_item.codegen_units { + expected_item.codegen_units != actual_item.codegen_units + { wrong_cgus.push((expected_item.clone(), actual_item.clone())); } } else { @@ -1911,11 +2044,11 @@ actual:\n\ } } - let unexpected: Vec<_> = - actual.iter() - .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name)) - .map(|acgu| acgu.string.clone()) - .collect(); + let unexpected: Vec<_> = actual + .iter() + .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name)) + .map(|acgu| acgu.string.clone()) + .collect(); if !missing.is_empty() { missing.sort(); @@ -1951,14 +2084,19 @@ actual:\n\ for &(ref expected_item, ref actual_item) in &wrong_cgus { println!("{}", expected_item.name); - println!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units)); - println!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units)); + println!( + " expected: {}", + codegen_units_to_str(&expected_item.codegen_units) + ); + println!( + " actual: {}", + codegen_units_to_str(&actual_item.codegen_units) + ); println!(""); } } - if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty()) - { + if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty()) { panic!(); } @@ -1980,22 +2118,22 @@ actual:\n\ let full_string = format!("{}{}", PREFIX, s.trim().to_owned()); let parts: Vec<&str> = s.split(CGU_MARKER) - .map(str::trim) - .filter(|s| !s.is_empty()) - .collect(); + .map(str::trim) + .filter(|s| !s.is_empty()) + .collect(); let name = parts[0].trim(); let cgus = if parts.len() > 1 { let cgus_str = parts[1]; - cgus_str.split(' ') - .map(str::trim) - .filter(|s| !s.is_empty()) - .map(str::to_owned) - .collect() - } - else { + cgus_str + .split(' ') + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(str::to_owned) + .collect() + } else { HashSet::new() }; @@ -2006,8 +2144,7 @@ actual:\n\ } } - fn codegen_units_to_str(cgus: &HashSet<String>) -> String - { + fn codegen_units_to_str(cgus: &HashSet<String>) -> String { let mut cgus: Vec<_> = cgus.iter().collect(); cgus.sort(); @@ -2038,7 +2175,10 @@ actual:\n\ fs::create_dir_all(&incremental_dir).unwrap(); if self.config.verbose { - print!("init_incremental_test: incremental_dir={}", incremental_dir.display()); + print!( + "init_incremental_test: incremental_dir={}", + incremental_dir.display() + ); } } @@ -2062,11 +2202,15 @@ actual:\n\ // FIXME -- use non-incremental mode as an oracle? That doesn't apply // to #[rustc_dirty] and clean tests I guess - let revision = self.revision.expect("incremental tests require a list of revisions"); + let revision = self.revision + .expect("incremental tests require a list of revisions"); // Incremental workproduct directory should have already been created. let incremental_dir = self.incremental_dir(); - assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir"); + assert!( + incremental_dir.exists(), + "init_incremental_test failed to create incremental dir" + ); // Add an extra flag pointing at the incremental directory. let mut revision_props = self.props.clone(); @@ -2080,7 +2224,11 @@ actual:\n\ }; if self.config.verbose { - print!("revision={:?} revision_props={:#?}", revision, revision_props); + print!( + "revision={:?} revision_props={:#?}", + revision, + revision_props + ); } if revision.starts_with("rpass") { @@ -2090,8 +2238,7 @@ actual:\n\ } else if revision.starts_with("cfail") { revision_cx.run_cfail_test(); } else { - revision_cx.fatal( - "revision name must begin with rpass, rfail, or cfail"); + revision_cx.fatal("revision name must begin with rpass, rfail, or cfail"); } } @@ -2103,13 +2250,18 @@ actual:\n\ fn run_rmake_test(&self) { // FIXME(#11094): we should fix these tests if self.config.host != self.config.target { - return + return; } let cwd = env::current_dir().unwrap(); - let src_root = self.config.src_base.parent().unwrap() - .parent().unwrap() - .parent().unwrap(); + let src_root = self.config + .src_base + .parent() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap(); let src_root = cwd.join(&src_root); let tmpdir = cwd.join(self.output_base_name()); @@ -2119,9 +2271,10 @@ actual:\n\ create_dir_all(&tmpdir).unwrap(); let host = &self.config.host; - let make = if host.contains("bitrig") || host.contains("dragonfly") || - host.contains("freebsd") || host.contains("netbsd") || - host.contains("openbsd") { + let make = if host.contains("bitrig") || host.contains("dragonfly") + || host.contains("freebsd") || host.contains("netbsd") + || host.contains("openbsd") + { "gmake" } else { "make" @@ -2129,21 +2282,26 @@ actual:\n\ let mut cmd = Command::new(make); cmd.current_dir(&self.testpaths.file) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .env("TARGET", &self.config.target) - .env("PYTHON", &self.config.docck_python) - .env("S", src_root) - .env("RUST_BUILD_STAGE", &self.config.stage_id) - .env("RUSTC", cwd.join(&self.config.rustc_path)) - .env("RUSTDOC", - cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"))) - .env("TMPDIR", &tmpdir) - .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) - .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) - .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) - .env("LLVM_COMPONENTS", &self.config.llvm_components) - .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags); + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .env("TARGET", &self.config.target) + .env("PYTHON", &self.config.docck_python) + .env("S", src_root) + .env("RUST_BUILD_STAGE", &self.config.stage_id) + .env("RUSTC", cwd.join(&self.config.rustc_path)) + .env( + "RUSTDOC", + cwd.join(&self.config + .rustdoc_path + .as_ref() + .expect("--rustdoc-path passed")), + ) + .env("TMPDIR", &tmpdir) + .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) + .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) + .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) + .env("LLVM_COMPONENTS", &self.config.llvm_components) + .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags); if let Some(ref linker) = self.config.linker { cmd.env("RUSTC_LINKER", linker); @@ -2161,25 +2319,31 @@ actual:\n\ // MSYS doesn't like passing flags of the form `/foo` as it thinks it's // a path and instead passes `C:\msys64\foo`, so convert all // `/`-arguments to MSVC here to `-` arguments. - let cflags = self.config.cflags.split(' ').map(|s| s.replace("/", "-")) - .collect::<Vec<_>>().join(" "); + let cflags = self.config + .cflags + .split(' ') + .map(|s| s.replace("/", "-")) + .collect::<Vec<_>>() + .join(" "); cmd.env("IS_MSVC", "1") - .env("IS_WINDOWS", "1") - .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) - .env("CC", format!("'{}' {}", self.config.cc, cflags)) - .env("CXX", &self.config.cxx); + .env("IS_WINDOWS", "1") + .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) + .env("CC", format!("'{}' {}", self.config.cc, cflags)) + .env("CXX", &self.config.cxx); } else { cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags)) - .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)) - .env("AR", &self.config.ar); + .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)) + .env("AR", &self.config.ar); if self.config.target.contains("windows") { cmd.env("IS_WINDOWS", "1"); } } - let output = cmd.spawn().and_then(read2_abbreviated).expect("failed to spawn `make`"); + let output = cmd.spawn() + .and_then(read2_abbreviated) + .expect("failed to spawn `make`"); if !output.status.success() { let res = ProcRes { status: output.status, @@ -2218,14 +2382,17 @@ actual:\n\ // if the user specified a format in the ui test // print the output to the stderr file, otherwise extract // the rendered error messages from json and print them - let explicit = self.props.compile_flags.iter().any(|s| s.contains("--error-format")); + let explicit = self.props + .compile_flags + .iter() + .any(|s| s.contains("--error-format")); let proc_res = self.compile_test(); - let expected_stderr_path = self.expected_output_path("stderr"); + let expected_stderr_path = self.expected_output_path(UI_STDERR); let expected_stderr = self.load_expected_output(&expected_stderr_path); - let expected_stdout_path = self.expected_output_path("stdout"); + let expected_stdout_path = self.expected_output_path(UI_STDOUT); let expected_stdout = self.load_expected_output(&expected_stdout_path); let normalized_stdout = @@ -2237,8 +2404,7 @@ actual:\n\ json::extract_rendered(&proc_res.stderr, &proc_res) }; - let normalized_stderr = - self.normalize_output(&stderr, &self.props.normalize_stderr); + let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); let mut errors = 0; errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); @@ -2246,15 +2412,19 @@ actual:\n\ if errors > 0 { println!("To update references, run this command from build directory:"); - let relative_path_to_file = - self.testpaths.relative_dir - .join(self.testpaths.file.file_name().unwrap()); - println!("{}/update-references.sh '{}' '{}'", - self.config.src_base.display(), - self.config.build_base.display(), - relative_path_to_file.display()); - self.fatal_proc_rec(&format!("{} errors occurred comparing output.", errors), - &proc_res); + let relative_path_to_file = self.testpaths + .relative_dir + .join(self.testpaths.file.file_name().unwrap()); + println!( + "{}/update-references.sh '{}' '{}'", + self.config.src_base.display(), + self.config.build_base.display(), + relative_path_to_file.display() + ); + self.fatal_proc_rec( + &format!("{} errors occurred comparing output.", errors), + &proc_res, + ); } let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); @@ -2294,13 +2464,14 @@ actual:\n\ fn check_mir_dump(&self) { let mut test_file_contents = String::new(); - fs::File::open(self.testpaths.file.clone()).unwrap() - .read_to_string(&mut test_file_contents) - .unwrap(); - if let Some(idx) = test_file_contents.find("// END RUST SOURCE") { + fs::File::open(self.testpaths.file.clone()) + .unwrap() + .read_to_string(&mut test_file_contents) + .unwrap(); + if let Some(idx) = test_file_contents.find("// END RUST SOURCE") { let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len()); let tests_text_str = String::from(tests_text); - let mut curr_test : Option<&str> = None; + let mut curr_test: Option<&str> = None; let mut curr_test_contents = vec![ExpectedLine::Elision]; for l in tests_text_str.lines() { debug!("line: {:?}", l); @@ -2334,9 +2505,16 @@ actual:\n\ let output_time = t(output_file); let source_time = t(source_file); if source_time > output_time { - debug!("source file time: {:?} output file time: {:?}", source_time, output_time); - panic!("test source file `{}` is newer than potentially stale output file `{}`.", - source_file.display(), test_name); + debug!( + "source file time: {:?} output file time: {:?}", + source_time, + output_time + ); + panic!( + "test source file `{}` is newer than potentially stale output file `{}`.", + source_file.display(), + test_name + ); } } @@ -2347,22 +2525,30 @@ actual:\n\ debug!("comparing the contests of: {:?}", output_file); debug!("with: {:?}", expected_content); if !output_file.exists() { - panic!("Output file `{}` from test does not exist", - output_file.into_os_string().to_string_lossy()); + panic!( + "Output file `{}` from test does not exist", + output_file.into_os_string().to_string_lossy() + ); } self.check_mir_test_timestamp(test_name, &output_file); let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); let mut dumped_string = String::new(); dumped_file.read_to_string(&mut dumped_string).unwrap(); - let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty()); - let mut expected_lines = expected_content.iter().filter(|&l| { - if let &ExpectedLine::Text(l) = l { - !l.is_empty() - } else { - true - } - }).peekable(); + let mut dumped_lines = dumped_string + .lines() + .map(|l| nocomment_mir_line(l)) + .filter(|l| !l.is_empty()); + let mut expected_lines = expected_content + .iter() + .filter(|&l| { + if let &ExpectedLine::Text(l) = l { + !l.is_empty() + } else { + true + } + }) + .peekable(); let compare = |expected_line, dumped_line| { let e_norm = normalize_mir_line(expected_line); @@ -2373,27 +2559,31 @@ actual:\n\ }; let error = |expected_line, extra_msg| { - let normalize_all = dumped_string.lines() - .map(nocomment_mir_line) - .filter(|l| !l.is_empty()) - .collect::<Vec<_>>() - .join("\n"); + let normalize_all = dumped_string + .lines() + .map(nocomment_mir_line) + .filter(|l| !l.is_empty()) + .collect::<Vec<_>>() + .join("\n"); let f = |l: &ExpectedLine<_>| match l { &ExpectedLine::Elision => "... (elided)".into(), - &ExpectedLine::Text(t) => t + &ExpectedLine::Text(t) => t, }; - let expected_content = expected_content.iter() - .map(|l| f(l)) - .collect::<Vec<_>>() - .join("\n"); - panic!("Did not find expected line, error: {}\n\ - Actual Line: {:?}\n\ - Expected:\n{}\n\ - Actual:\n{}", - extra_msg, - expected_line, - expected_content, - normalize_all); + let expected_content = expected_content + .iter() + .map(|l| f(l)) + .collect::<Vec<_>>() + .join("\n"); + panic!( + "Did not find expected line, error: {}\n\ + Expected Line: {:?}\n\ + Expected:\n{}\n\ + Actual:\n{}", + extra_msg, + expected_line, + expected_content, + normalize_all + ); }; // We expect each non-empty line to appear consecutively, non-consecutive lines @@ -2409,11 +2599,18 @@ actual:\n\ if !compare(expected_line, dumped_line) { error!("{:?}", start_block_line); - error(expected_line, - format!("Mismatch in lines\nCurrnt block: {}\nExpected Line: {:?}", - start_block_line.unwrap_or("None"), dumped_line)); + error( + expected_line, + format!( + "Mismatch in lines\n\ + Current block: {}\n\ + Actual Line: {:?}", + start_block_line.unwrap_or("None"), + dumped_line + ), + ); } - }, + } Some(&ExpectedLine::Elision) => { // skip any number of elisions in a row. while let Some(&&ExpectedLine::Elision) = expected_lines.peek() { @@ -2434,8 +2631,8 @@ actual:\n\ error(expected_line, "ran out of mir dump to match against".into()); } } - }, - None => {}, + } + None => {} } } } @@ -2451,10 +2648,10 @@ actual:\n\ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { let parent_dir = self.testpaths.file.parent().unwrap(); let cflags = self.props.compile_flags.join(" "); - let json = cflags.contains("--error-format json") || - cflags.contains("--error-format pretty-json") || - cflags.contains("--error-format=json") || - cflags.contains("--error-format=pretty-json"); + let json = cflags.contains("--error-format json") + || cflags.contains("--error-format pretty-json") + || cflags.contains("--error-format=json") + || cflags.contains("--error-format=pretty-json"); let parent_dir_str = if json { parent_dir.display().to_string().replace("\\", "\\\\") } else { @@ -2482,11 +2679,7 @@ actual:\n\ } fn expected_output_path(&self, kind: &str) -> PathBuf { - let extension = match self.revision { - Some(r) => format!("{}.{}", r, kind), - None => kind.to_string(), - }; - self.testpaths.file.with_extension(extension) + expected_output_path(&self.testpaths, self.revision, kind) } fn load_expected_output(&self, path: &Path) -> String { @@ -2497,10 +2690,11 @@ actual:\n\ let mut result = String::new(); match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) { Ok(_) => result, - Err(e) => { - self.fatal(&format!("failed to load expected output from `{}`: {}", - path.display(), e)) - } + Err(e) => self.fatal(&format!( + "failed to load expected output from `{}`: {}", + path.display(), + e + )), } } @@ -2515,19 +2709,21 @@ actual:\n\ for diff in diff::lines(expected, actual) { match diff { - diff::Result::Left(l) => println!("-{}", l), + diff::Result::Left(l) => println!("-{}", l), diff::Result::Both(l, _) => println!(" {}", l), - diff::Result::Right(r) => println!("+{}", r), + diff::Result::Right(r) => println!("+{}", r), } } let output_file = self.output_base_name().with_extension(kind); match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) { - Ok(()) => { } - Err(e) => { - self.fatal(&format!("failed to write {} to `{}`: {}", - kind, output_file.display(), e)) - } + Ok(()) => {} + Err(e) => self.fatal(&format!( + "failed to write {} to `{}`: {}", + kind, + output_file.display(), + e + )), } println!("\nThe actual {0} differed from the expected {0}.", kind); @@ -2553,20 +2749,24 @@ impl ProcRes { if let Some(e) = err { println!("\nerror: {}", e); } - print!("\ - status: {}\n\ - command: {}\n\ - stdout:\n\ - ------------------------------------------\n\ - {}\n\ - ------------------------------------------\n\ - stderr:\n\ - ------------------------------------------\n\ - {}\n\ - ------------------------------------------\n\ - \n", - self.status, self.cmdline, self.stdout, - self.stderr); + print!( + "\ + status: {}\n\ + command: {}\n\ + stdout:\n\ + ------------------------------------------\n\ + {}\n\ + ------------------------------------------\n\ + stderr:\n\ + ------------------------------------------\n\ + {}\n\ + ------------------------------------------\n\ + \n", + self.status, + self.cmdline, + self.stdout, + self.stderr + ); panic!(); } } @@ -2579,12 +2779,12 @@ enum TargetLocation { #[derive(Clone, PartialEq, Eq)] enum ExpectedLine<T: AsRef<str>> { Elision, - Text(T) + Text(T), } impl<T> fmt::Debug for ExpectedLine<T> where - T: AsRef<str> + fmt::Debug + T: AsRef<str> + fmt::Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if let &ExpectedLine::Text(ref t) = self { @@ -2621,7 +2821,7 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> { head: Vec<u8>, skipped: usize, tail: Box<[u8]>, - } + }, } impl ProcOutput { @@ -2636,9 +2836,17 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> { let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice(); let head = replace(bytes, Vec::new()); let skipped = new_len - HEAD_LEN - TAIL_LEN; - ProcOutput::Abbreviated { head, skipped, tail } + ProcOutput::Abbreviated { + head, + skipped, + tail, + } } - ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => { + ProcOutput::Abbreviated { + ref mut skipped, + ref mut tail, + .. + } => { *skipped += data.len(); if data.len() <= TAIL_LEN { tail[..data.len()].copy_from_slice(data); @@ -2655,7 +2863,11 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> { fn into_bytes(self) -> Vec<u8> { match self { ProcOutput::Full(bytes) => bytes, - ProcOutput::Abbreviated { mut head, skipped, tail } => { + ProcOutput::Abbreviated { + mut head, + skipped, + tail, + } => { write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap(); head.extend_from_slice(&tail); head @@ -2668,10 +2880,14 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> { let mut stderr = ProcOutput::Full(Vec::new()); drop(child.stdin.take()); - read2(child.stdout.take().unwrap(), child.stderr.take().unwrap(), &mut |is_stdout, data, _| { - if is_stdout { &mut stdout } else { &mut stderr }.extend(data); - data.clear(); - })?; + read2( + child.stdout.take().unwrap(), + child.stderr.take().unwrap(), + &mut |is_stdout, data, _| { + if is_stdout { &mut stdout } else { &mut stderr }.extend(data); + data.clear(); + }, + )?; let status = child.wait()?; Ok(Output { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 9736c039930..eca225ee8a8 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -89,7 +89,9 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) { let mut contents = String::new(); - super::walk_many(&[&path.join("test/compile-fail"), + super::walk_many(&[&path.join("test/ui-fulldeps"), + &path.join("test/ui"), + &path.join("test/compile-fail"), &path.join("test/compile-fail-fulldeps"), &path.join("test/parse-fail"),], &mut |path| super::filter_dirs(path), @@ -150,9 +152,9 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) { for &(name, _) in gate_untested.iter() { println!("Expected a gate test for the feature '{}'.", name); - println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\ - \n test suite, with its failures due to missing usage of\ - \n #![feature({})].", name, name); + println!("Hint: create a failing test file named 'feature-gate-{}.rs'\ + \n in the 'ui' test suite, with its failures due to\ + \n missing usage of #![feature({})].", name, name); println!("Hint: If you already have such a test and don't want to rename it,\ \n you can also add a // gate-test-{} line to the test file.", name); |
