diff options
Diffstat (limited to 'src')
134 files changed, 2121 insertions, 760 deletions
diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md index 6ce75efd103..22cf6068e4d 100644 --- a/src/doc/book/guessing-game.md +++ b/src/doc/book/guessing-game.md @@ -365,7 +365,7 @@ numbers. A bare number like above is actually shorthand for `^0.3.0`, meaning "anything compatible with 0.3.0". If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"` (note the two equal signs). -And if we wanted to use the latest version we could use `*`. +And if we wanted to use the latest version we could use `rand="*"`. We could also use a range of versions. [Cargo’s documentation][cargodoc] contains more details. diff --git a/src/doc/book/the-stack-and-the-heap.md b/src/doc/book/the-stack-and-the-heap.md index a1f6a065a25..aee45299cf2 100644 --- a/src/doc/book/the-stack-and-the-heap.md +++ b/src/doc/book/the-stack-and-the-heap.md @@ -26,6 +26,8 @@ The stack is very fast, and is where memory is allocated in Rust by default. But the allocation is local to a function call, and is limited in size. The heap, on the other hand, is slower, and is explicitly allocated by your program. But it’s effectively unlimited in size, and is globally accessible. +Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary +order, is quite different from the heap data structure. # The Stack diff --git a/src/doc/reference.md b/src/doc/reference.md index a461023642a..f4ffe5774d2 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3049,7 +3049,8 @@ as == != < > <= >= && || -= .. +.. ... += ``` Operators at the same precedence level are evaluated left-to-right. [Unary diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index 4e39191b472..1badc72aed0 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -23,6 +23,22 @@ pub trait RangeArgument<T> { /// Start index (inclusive) /// /// Return start value if present, else `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections)] + /// #![feature(collections_range)] + /// + /// extern crate collections; + /// + /// # fn main() { + /// use collections::range::RangeArgument; + /// + /// assert_eq!((..10).start(), None); + /// assert_eq!((3..10).start(), Some(&3)); + /// # } + /// ``` fn start(&self) -> Option<&T> { None } @@ -30,6 +46,22 @@ pub trait RangeArgument<T> { /// End index (exclusive) /// /// Return end value if present, else `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections)] + /// #![feature(collections_range)] + /// + /// extern crate collections; + /// + /// # fn main() { + /// use collections::range::RangeArgument; + /// + /// assert_eq!((3..).end(), None); + /// assert_eq!((3..10).end(), Some(&10)); + /// # } + /// ``` fn end(&self) -> Option<&T> { None } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 275f38b2f78..8b4fce158de 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -476,6 +476,25 @@ impl<T> Vec<T> { /// Note that this will drop any excess capacity. Calling this and /// converting back to a vector with `into_vec()` is equivalent to calling /// `shrink_to_fit()`. + /// + /// # Examples + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + /// + /// Any excess capacity is removed: + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// + /// assert_eq!(vec.capacity(), 10); + /// let slice = vec.into_boxed_slice(); + /// assert_eq!(slice.into_vec().capacity(), 3); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T]> { unsafe { diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index c18d230be31..894982abaa9 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -144,6 +144,12 @@ pub trait Unsize<T: ?Sized> { /// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's /// managing some resource besides its own `size_of::<T>()` bytes. /// +/// ## What if I derive `Copy` on a type that can't? +/// +/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error. +/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204) +/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205). +/// /// ## When should my type be `Copy`? /// /// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 6b2122451db..a7d0d3899b1 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -34,12 +34,13 @@ /// only designed to be used by unsafe code that needs to manipulate /// the low-level details. /// -/// There is no `Repr` implementation for `TraitObject` because there -/// is no way to refer to all trait objects generically, so the only +/// There is no way to refer to all trait objects generically, so the only /// way to create values of this type is with functions like -/// `std::mem::transmute`. Similarly, the only way to create a true +/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true /// trait object from a `TraitObject` value is with `transmute`. /// +/// [transmute]: ../intrinsics/fn.transmute.html +/// /// Synthesizing a trait object with mismatched types—one where the /// vtable does not correspond to the type of the value to which the /// data pointer points—is highly likely to lead to undefined @@ -50,13 +51,13 @@ /// ``` /// #![feature(raw)] /// -/// use std::mem; -/// use std::raw; +/// use std::{mem, raw}; /// /// // an example trait /// trait Foo { /// fn bar(&self) -> i32; /// } +/// /// impl Foo for i32 { /// fn bar(&self) -> i32 { /// *self + 1 @@ -74,7 +75,6 @@ /// // the data pointer is the address of `value` /// assert_eq!(raw_object.data as *const i32, &value as *const _); /// -/// /// let other_value: i32 = 456; /// /// // construct a new object, pointing to a different `i32`, being @@ -82,11 +82,11 @@ /// let synthesized: &Foo = unsafe { /// mem::transmute(raw::TraitObject { /// data: &other_value as *const _ as *mut (), -/// vtable: raw_object.vtable +/// vtable: raw_object.vtable, /// }) /// }; /// -/// // it should work just like we constructed a trait object out of +/// // it should work just as if we had constructed a trait object out of /// // `other_value` directly /// assert_eq!(synthesized.bar(), 457); /// ``` diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 20bf4f7d3ed..9212fda6502 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -36,7 +36,7 @@ use hir::def::Def; use hir::def_id::DefId; use util::nodemap::{NodeMap, FnvHashSet}; -use syntax_pos::{mk_sp, Span, ExpnId}; +use syntax_pos::{BytePos, mk_sp, Span, ExpnId}; use syntax::codemap::{self, respan, Spanned}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; @@ -326,6 +326,38 @@ impl Generics { pub fn is_parameterized(&self) -> bool { self.is_lt_parameterized() || self.is_type_parameterized() } + + // Does return a span which includes lifetimes and type parameters, + // not where clause. + pub fn span(&self) -> Option<Span> { + if !self.is_parameterized() { + None + } else { + let mut span: Option<Span> = None; + for lifetime in self.lifetimes.iter() { + if let Some(ref mut span) = span { + let life_span = lifetime.lifetime.span; + span.hi = if span.hi > life_span.hi { span.hi } else { life_span.hi }; + span.lo = if span.lo < life_span.lo { span.lo } else { life_span.lo }; + } else { + span = Some(lifetime.lifetime.span.clone()); + } + } + for ty_param in self.ty_params.iter() { + if let Some(ref mut span) = span { + span.lo = if span.lo < ty_param.span.lo { span.lo } else { ty_param.span.lo }; + span.hi = if span.hi > ty_param.span.hi { span.hi } else { ty_param.span.hi }; + } else { + span = Some(ty_param.span.clone()); + } + } + if let Some(ref mut span) = span { + span.lo = span.lo - BytePos(1); + span.hi = span.hi + BytePos(1); + } + span + } + } } /// A `where` clause in a definition diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index e856eb84ff2..86422835c8c 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -24,13 +24,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) { for segment in segments { for typ in segment.parameters.types() { - span_err!(self.sess, typ.span, E0109, - "type parameters are not allowed on this type"); + struct_span_err!(self.sess, typ.span, E0109, + "type parameters are not allowed on this type") + .span_label(typ.span, &format!("type parameter not allowed")) + .emit(); break; } for lifetime in segment.parameters.lifetimes() { - span_err!(self.sess, lifetime.span, E0110, - "lifetime parameters are not allowed on this type"); + struct_span_err!(self.sess, lifetime.span, E0110, + "lifetime parameters are not allowed on this type") + .span_label(lifetime.span, + &format!("lifetime parameter not allowed on this type")) + .emit(); break; } for binding in segment.parameters.bindings() { @@ -42,8 +47,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn prohibit_projection(self, span: Span) { - span_err!(self.sess, span, E0229, - "associated type bindings are not allowed here"); + let mut err = struct_span_err!(self.sess, span, E0229, + "associated type bindings are not allowed here"); + err.span_label(span, &format!("associate type not allowed here")).emit(); } pub fn prim_ty_to_ty(self, diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 23a261400ed..0a363fddd53 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -121,8 +121,11 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) { if ctxt.attr_main_fn.is_none() { ctxt.attr_main_fn = Some((item.id, item.span)); } else { - span_err!(ctxt.session, item.span, E0137, - "multiple functions with a #[main] attribute"); + struct_span_err!(ctxt.session, item.span, E0137, + "multiple functions with a #[main] attribute") + .span_label(item.span, &format!("additional #[main] function")) + .span_label(ctxt.attr_main_fn.unwrap().1, &format!("first #[main] function")) + .emit(); } }, EntryPointType::Start => { diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index ffa1530a14e..93c6dd09e07 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -17,7 +17,6 @@ //! - not reference the erased type `Self` except for in this receiver; //! - not have generic type parameters -use super::supertraits; use super::elaborate_predicates; use hir::def_id::DefId; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index fadf3647155..d9ffe36ea47 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -10,7 +10,6 @@ //! misc. type-system utilities too small to deserve their own file -use hir::svh::Svh; use hir::def_id::DefId; use ty::subst; use infer::InferCtxt; @@ -18,6 +17,7 @@ use hir::pat_util; use traits::{self, ProjectionMode}; use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; use ty::{Disr, ParameterEnvironment}; +use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; use ty::TypeVariants::*; @@ -25,6 +25,7 @@ use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use std::cmp; use std::hash::{Hash, SipHasher, Hasher}; +use std::intrinsics; use syntax::ast::{self, Name}; use syntax::attr::{self, SignedInt, UnsignedInt}; use syntax_pos::Span; @@ -350,148 +351,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. - pub fn hash_crate_independent(self, ty: Ty<'tcx>, svh: &Svh) -> u64 { - let mut state = SipHasher::new(); - helper(self, ty, svh, &mut state); - return state.finish(); - - fn helper<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, svh: &Svh, - state: &mut SipHasher) { - macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } } - macro_rules! hash { ($e:expr) => { $e.hash(state) } } - - let region = |state: &mut SipHasher, r: ty::Region| { - match r { - ty::ReStatic | ty::ReErased => {} - ty::ReLateBound(db, ty::BrAnon(i)) => { - db.hash(state); - i.hash(state); - } - ty::ReEmpty | - ty::ReEarlyBound(..) | - ty::ReLateBound(..) | - ty::ReFree(..) | - ty::ReScope(..) | - ty::ReVar(..) | - ty::ReSkolemized(..) => { - bug!("unexpected region found when hashing a type") - } - } - }; - let did = |state: &mut SipHasher, did: DefId| { - let h = if did.is_local() { - svh.clone() - } else { - tcx.sess.cstore.crate_hash(did.krate) - }; - h.hash(state); - did.index.hash(state); - }; - let mt = |state: &mut SipHasher, mt: TypeAndMut| { - mt.mutbl.hash(state); - }; - let fn_sig = |state: &mut SipHasher, sig: &ty::Binder<ty::FnSig<'tcx>>| { - let sig = tcx.anonymize_late_bound_regions(sig).0; - for a in &sig.inputs { helper(tcx, *a, svh, state); } - if let ty::FnConverging(output) = sig.output { - helper(tcx, output, svh, state); - } - }; - ty.maybe_walk(|ty| { - match ty.sty { - TyBool => byte!(2), - TyChar => byte!(3), - TyInt(i) => { - byte!(4); - hash!(i); - } - TyUint(u) => { - byte!(5); - hash!(u); - } - TyFloat(f) => { - byte!(6); - hash!(f); - } - TyStr => { - byte!(7); - } - TyEnum(d, _) => { - byte!(8); - did(state, d.did); - } - TyBox(_) => { - byte!(9); - } - TyArray(_, n) => { - byte!(10); - n.hash(state); - } - TySlice(_) => { - byte!(11); - } - TyRawPtr(m) => { - byte!(12); - mt(state, m); - } - TyRef(r, m) => { - byte!(13); - region(state, *r); - mt(state, m); - } - TyFnDef(def_id, _, _) => { - byte!(14); - hash!(def_id); - } - TyFnPtr(ref b) => { - byte!(15); - hash!(b.unsafety); - hash!(b.abi); - fn_sig(state, &b.sig); - return false; - } - TyTrait(ref data) => { - byte!(17); - did(state, data.principal_def_id()); - hash!(data.bounds); - - let principal = tcx.anonymize_late_bound_regions(&data.principal).0; - for subty in &principal.substs.types { - helper(tcx, subty, svh, state); - } - - return false; - } - TyStruct(d, _) => { - byte!(18); - did(state, d.did); - } - TyTuple(ref inner) => { - byte!(19); - hash!(inner.len()); - } - TyParam(p) => { - byte!(20); - hash!(p.space); - hash!(p.idx); - hash!(p.name.as_str()); - } - TyInfer(_) => bug!(), - TyError => byte!(21), - TyClosure(d, _) => { - byte!(22); - did(state, d); - } - TyProjection(ref data) => { - byte!(23); - did(state, data.trait_ref.def_id); - hash!(data.item_name.as_str()); - } - } - true - }); - } + pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { + let mut hasher = TypeIdHasher { + tcx: self, + state: SipHasher::new() + }; + hasher.visit_ty(ty); + hasher.state.finish() } /// Returns true if this ADT is a dtorck type. @@ -525,6 +391,143 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } +struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + state: SipHasher +} + +impl<'a, 'gcx, 'tcx> TypeIdHasher<'a, 'gcx, 'tcx> { + fn hash<T: Hash>(&mut self, x: T) { + x.hash(&mut self.state); + } + + fn hash_discriminant_u8<T>(&mut self, x: &T) { + let v = unsafe { + intrinsics::discriminant_value(x) + }; + let b = v as u8; + assert_eq!(v, b as u64); + self.hash(b) + } + + fn def_id(&mut self, did: DefId) { + // Hash the crate identification information. + let name = self.tcx.crate_name(did.krate); + let disambiguator = self.tcx.crate_disambiguator(did.krate); + self.hash((name, disambiguator)); + + // Hash the item path within that crate. + // FIXME(#35379) This should use a deterministic + // DefPath hashing mechanism, not the DefIndex. + self.hash(did.index); + } +} + +impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + // Distinguish between the Ty variants uniformly. + self.hash_discriminant_u8(&ty.sty); + + match ty.sty { + TyInt(i) => self.hash(i), + TyUint(u) => self.hash(u), + TyFloat(f) => self.hash(f), + TyStruct(d, _) | + TyEnum(d, _) => self.def_id(d.did), + TyArray(_, n) => self.hash(n), + TyRawPtr(m) | + TyRef(_, m) => self.hash(m.mutbl), + TyClosure(def_id, _) | + TyFnDef(def_id, _, _) => self.def_id(def_id), + TyFnPtr(f) => { + self.hash(f.unsafety); + self.hash(f.abi); + self.hash(f.sig.variadic()); + } + TyTrait(ref data) => { + // Trait objects have a list of projection bounds + // that are not guaranteed to be sorted in an order + // that gets preserved across crates, so we need + // to sort them again by the name, in string form. + + // Hash the whole principal trait ref. + self.def_id(data.principal_def_id()); + data.principal.visit_with(self); + + // Hash region and builtin bounds. + data.bounds.region_bound.visit_with(self); + self.hash(data.bounds.builtin_bounds); + + // Only projection bounds are left, sort and hash them. + let mut projection_bounds: Vec<_> = data.bounds.projection_bounds + .iter() + .map(|b| (b.item_name().as_str(), b)) + .collect(); + projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); + for (name, bound) in projection_bounds { + self.def_id(bound.0.projection_ty.trait_ref.def_id); + self.hash(name); + bound.visit_with(self); + } + + // Bypass super_visit_with, we've visited everything. + return false; + } + TyTuple(tys) => { + self.hash(tys.len()); + } + TyParam(p) => { + self.hash(p.space); + self.hash(p.idx); + self.hash(p.name.as_str()); + } + TyProjection(ref data) => { + self.def_id(data.trait_ref.def_id); + self.hash(data.item_name.as_str()); + } + TyBool | + TyChar | + TyStr | + TyBox(_) | + TySlice(_) | + TyError => {} + TyInfer(_) => bug!() + } + + ty.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region) -> bool { + match r { + ty::ReStatic | ty::ReErased => { + self.hash::<u32>(0); + } + ty::ReLateBound(db, ty::BrAnon(i)) => { + assert!(db.depth > 0); + self.hash::<u32>(db.depth); + self.hash(i); + } + ty::ReEmpty | + ty::ReEarlyBound(..) | + ty::ReLateBound(..) | + ty::ReFree(..) | + ty::ReScope(..) | + ty::ReVar(..) | + ty::ReSkolemized(..) => { + bug!("unexpected region found when hashing a type") + } + } + false + } + + fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, x: &ty::Binder<T>) -> bool { + // Anonymize late-bound regions so that, for example: + // `for<'a, b> fn(&'a &'b T)` and `for<'a, b> fn(&'b &'a T)` + // result in the same TypeId (the two types are equivalent). + self.tcx.anonymize_late_bound_regions(x).super_visit_with(self) + } +} + impl<'a, 'tcx> ty::TyS<'tcx> { fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: &ParameterEnvironment<'tcx>, diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 1fe47cd4853..9115fd42be8 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -942,9 +942,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { but it borrows {}, \ which is owned by the current function", cmt_path_or_string) - .span_note(capture_span, + .span_label(capture_span, &format!("{} is borrowed here", cmt_path_or_string)) + .span_label(err.span, + &format!("may outlive borrowed value {}", + cmt_path_or_string)) .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index d3952de2fbe..2fe4ae627c1 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -335,6 +335,7 @@ fn check_arms(cx: &MatchCheckCtxt, hir::MatchSource::Normal => { let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"); + err.span_label(pat.span, &format!("this is an unreachable pattern")); // if we had a catchall pattern, hint at that for row in &seen.0 { if pat_is_catchall(&cx.tcx.def_map.borrow(), row[0].0) { @@ -423,10 +424,15 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, format!("`{}` and {} more", head.join("`, `"), tail.len()) } }; - span_err!(cx.tcx.sess, sp, E0004, + + let label_text = match pattern_strings.len(){ + 1 => format!("pattern {} not covered", joined_patterns), + _ => format!("patterns {} not covered", joined_patterns) + }; + struct_span_err!(cx.tcx.sess, sp, E0004, "non-exhaustive patterns: {} not covered", joined_patterns - ); + ).span_label(sp, &label_text).emit(); }, } } diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 45414c33c07..9cdc76f25a6 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -25,8 +25,8 @@ one is too specific or the ordering is incorrect. For example, the following `match` block has too many arms: -```compile_fail -match foo { +```compile_fail,E0001 +match Some(0) { Some(bar) => {/* ... */} None => {/* ... */} _ => {/* ... */} // All possible cases have already been handled @@ -108,7 +108,7 @@ one or more possible inputs to a match expression. Guaranteed matches are required in order to assign values to match expressions, or alternatively, determine the flow of execution. Erroneous code example: -```compile_fail +```compile_fail,E0004 enum Terminator { HastaLaVistaBaby, TalkToMyHand, @@ -153,7 +153,7 @@ E0005: r##" Patterns used to bind names must be irrefutable, that is, they must guarantee that a name will be extracted in all cases. Erroneous code example: -```compile_fail +```compile_fail,E0005 let x = Some(1); let Some(y) = x; // error: refutable pattern in local binding: `None` not covered @@ -187,7 +187,7 @@ like the following is invalid as it requires the entire `Option<String>` to be moved into a variable called `op_string` while simultaneously requiring the inner `String` to be moved into a variable called `s`. -```compile_fail +```compile_fail,E0007 let x = Some("s".to_string()); match x { @@ -205,7 +205,7 @@ name is bound by move in a pattern, it should also be moved to wherever it is referenced in the pattern guard code. Doing so however would prevent the name from being available in the body of the match arm. Consider the following: -```compile_fail +```compile_fail,E0008 match Some("hi".to_string()) { Some(s) if s.len() == 0 => {}, // use s. _ => {}, @@ -229,7 +229,7 @@ match Some("hi".to_string()) { Though this example seems innocuous and easy to solve, the problem becomes clear when it encounters functions which consume the value: -```compile_fail +```compile_fail,E0008 struct A{} impl A { @@ -283,7 +283,7 @@ This limitation may be removed in a future version of Rust. Erroneous code example: -```compile_fail +```compile_fail,E0009 struct X { x: (), } let x = Some((X { x: () }, X { x: () })); @@ -351,25 +351,25 @@ An if-let pattern attempts to match the pattern, and enters the body if the match was successful. If the match is irrefutable (when it cannot fail to match), use a regular `let`-binding instead. For instance: -```compile_fail +```compile_fail,E0162 struct Irrefutable(i32); let irr = Irrefutable(0); // This fails to compile because the match is irrefutable. if let Irrefutable(x) = irr { // This body will always be executed. - foo(x); + // ... } ``` Try this instead: -```ignore +``` struct Irrefutable(i32); let irr = Irrefutable(0); let Irrefutable(x) = irr; -foo(x); +println!("{}", x); ``` "##, @@ -378,7 +378,7 @@ A while-let pattern attempts to match the pattern, and enters the body if the match was successful. If the match is irrefutable (when it cannot fail to match), use a regular `let`-binding inside a `loop` instead. For instance: -```compile_fail +```compile_fail,E0165 struct Irrefutable(i32); let irr = Irrefutable(0); @@ -455,7 +455,7 @@ that a name will be extracted in all cases. Instead of pattern matching the loop variable, consider using a `match` or `if let` inside the loop body. For instance: -```compile_fail +```compile_fail,E0297 let xs : Vec<Option<i32>> = vec!(Some(1), None); // This fails because `None` is not covered. @@ -497,7 +497,7 @@ on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if mutable borrows were allowed: -```compile_fail +```compile_fail,E0301 match Some(()) { None => { }, option if option.take().is_none() => { @@ -515,10 +515,10 @@ on which the match depends in such a way, that the match would not be exhaustive. For instance, the following would not match any arm if assignments were allowed: -```compile_fail +```compile_fail,E0302 match Some(()) { None => { }, - option if { option = None; false } { }, + option if { option = None; false } => { }, Some(_) => { } // When the previous match failed, the option became `None`. } ``` @@ -529,14 +529,18 @@ In certain cases it is possible for sub-bindings to violate memory safety. Updates to the borrow checker in a future version of Rust may remove this restriction, but for now patterns must be rewritten without sub-bindings. -```ignore -// Before. +Before: + +```compile_fail,E0303 match Some("hi".to_string()) { ref op_string_ref @ Some(s) => {}, None => {}, } +``` + +After: -// After. +``` match Some("hi".to_string()) { Some(ref s) => { let op_string_ref = &Some(s); @@ -556,7 +560,7 @@ This error indicates that the compiler was unable to sensibly evaluate an constant expression that had to be evaluated. Attempting to divide by 0 or causing integer overflow are two ways to induce this error. For example: -```compile_fail +```compile_fail,E0080 enum Enum { X = (1 << 500), Y = (1 / 0) @@ -575,7 +579,7 @@ E0306: r##" In an array literal `[x; N]`, `N` is the number of elements in the array. This must be an unsigned integer. Erroneous code example: -```compile_fail +```compile_fail,E0306 let x = [0i32; true]; // error: expected positive integer for repeat count, // found boolean ``` diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index d424b57c938..43d9725baaf 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -1337,10 +1337,13 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Ok(val as usize) }, Ok(const_val) => { - span_err!(tcx.sess, count_expr.span, E0306, - "expected usize for {}, found {}", - reason, - const_val.description()); + struct_span_err!(tcx.sess, count_expr.span, E0306, + "expected `usize` for {}, found {}", + reason, + const_val.description()) + .span_label(count_expr.span, &format!("expected `usize`")) + .emit(); + Err(ErrorReported) } Err(err) => { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index d2cf48eddeb..91d2500564f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -38,16 +38,18 @@ impl<'a> AstValidator<'a> { self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name)); } if label.name.as_str() == "'_" { - self.session.add_lint( - lint::builtin::LIFETIME_UNDERSCORE, id, span, - format!("invalid label name `{}`", label.name) - ); + self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE, + id, + span, + format!("invalid label name `{}`", label.name)); } } fn invalid_visibility(&self, vis: &Visibility, span: Span, note: Option<&str>) { if vis != &Visibility::Inherited { - let mut err = struct_span_err!(self.session, span, E0449, + let mut err = struct_span_err!(self.session, + span, + E0449, "unnecessary visibility qualifier"); if let Some(note) = note { err.span_note(span, note); @@ -71,10 +73,10 @@ impl<'a> AstValidator<'a> { impl<'a> Visitor for AstValidator<'a> { fn visit_lifetime(&mut self, lt: &Lifetime) { if lt.name.as_str() == "'_" { - self.session.add_lint( - lint::builtin::LIFETIME_UNDERSCORE, lt.id, lt.span, - format!("invalid lifetime name `{}`", lt.name) - ); + self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE, + lt.id, + lt.span, + format!("invalid lifetime name `{}`", lt.name)); } visit::walk_lifetime(self, lt) @@ -82,9 +84,12 @@ impl<'a> Visitor for AstValidator<'a> { fn visit_expr(&mut self, expr: &Expr) { match expr.node { - ExprKind::While(_, _, Some(ident)) | ExprKind::Loop(_, Some(ident)) | - ExprKind::WhileLet(_, _, _, Some(ident)) | ExprKind::ForLoop(_, _, _, Some(ident)) | - ExprKind::Break(Some(ident)) | ExprKind::Continue(Some(ident)) => { + ExprKind::While(_, _, Some(ident)) | + ExprKind::Loop(_, Some(ident)) | + ExprKind::WhileLet(_, _, _, Some(ident)) | + ExprKind::ForLoop(_, _, _, Some(ident)) | + ExprKind::Break(Some(ident)) | + ExprKind::Continue(Some(ident)) => { self.check_label(ident.node, ident.span, expr.id); } _ => {} @@ -97,10 +102,13 @@ impl<'a> Visitor for AstValidator<'a> { match ty.node { TyKind::BareFn(ref bfty) => { self.check_decl_no_pat(&bfty.decl, |span, _| { - let mut err = struct_span_err!(self.session, span, E0561, - "patterns aren't allowed in function pointer types"); - err.span_note(span, "this is a recent error, see \ - issue #35203 for more details"); + let mut err = struct_span_err!(self.session, + span, + E0561, + "patterns aren't allowed in function pointer \ + types"); + err.span_note(span, + "this is a recent error, see issue #35203 for more details"); err.emit(); }); } @@ -114,10 +122,10 @@ impl<'a> Visitor for AstValidator<'a> { if path.global && path.segments.len() > 0 { let ident = path.segments[0].identifier; if token::Ident(ident).is_path_segment_keyword() { - self.session.add_lint( - lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH, id, path.span, - format!("global paths cannot start with `{}`", ident) - ); + self.session.add_lint(lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH, + id, + path.span, + format!("global paths cannot start with `{}`", ident)); } } @@ -129,8 +137,8 @@ impl<'a> Visitor for AstValidator<'a> { ItemKind::Use(ref view_path) => { let path = view_path.node.path(); if !path.segments.iter().all(|segment| segment.parameters.is_empty()) { - self.err_handler().span_err(path.span, "type or lifetime parameters \ - in import path"); + self.err_handler() + .span_err(path.span, "type or lifetime parameters in import path"); } } ItemKind::Impl(_, _, _, Some(..), _, ref impl_items) => { @@ -140,15 +148,18 @@ impl<'a> Visitor for AstValidator<'a> { } } ItemKind::Impl(_, _, _, None, _, _) => { - self.invalid_visibility(&item.vis, item.span, Some("place qualifiers on individual \ - impl items instead")); + self.invalid_visibility(&item.vis, + item.span, + Some("place qualifiers on individual impl items instead")); } ItemKind::DefaultImpl(..) => { self.invalid_visibility(&item.vis, item.span, None); } ItemKind::ForeignMod(..) => { - self.invalid_visibility(&item.vis, item.span, Some("place qualifiers on individual \ - foreign items instead")); + self.invalid_visibility(&item.vis, + item.span, + Some("place qualifiers on individual foreign items \ + instead")); } ItemKind::Enum(ref def, _) => { for variant in &def.variants { @@ -167,11 +178,14 @@ impl<'a> Visitor for AstValidator<'a> { match fi.node { ForeignItemKind::Fn(ref decl, _) => { self.check_decl_no_pat(decl, |span, is_recent| { - let mut err = struct_span_err!(self.session, span, E0130, - "patterns aren't allowed in foreign function declarations"); + let mut err = struct_span_err!(self.session, + span, + E0130, + "patterns aren't allowed in foreign function \ + declarations"); if is_recent { - err.span_note(span, "this is a recent error, see \ - issue #35203 for more details"); + err.span_note(span, + "this is a recent error, see issue #35203 for more details"); } err.emit(); }); @@ -182,16 +196,21 @@ impl<'a> Visitor for AstValidator<'a> { visit::walk_foreign_item(self, fi) } - fn visit_variant_data(&mut self, vdata: &VariantData, _: Ident, - _: &Generics, _: NodeId, span: Span) { + fn visit_variant_data(&mut self, + vdata: &VariantData, + _: Ident, + _: &Generics, + _: NodeId, + span: Span) { if vdata.fields().is_empty() { if vdata.is_tuple() { - self.err_handler().struct_span_err(span, "empty tuple structs and enum variants \ - are not allowed, use unit structs and \ - enum variants instead") - .span_help(span, "remove trailing `()` to make a unit \ - struct or unit enum variant") - .emit(); + self.err_handler() + .struct_span_err(span, + "empty tuple structs and enum variants are not allowed, use \ + unit structs and enum variants instead") + .span_help(span, + "remove trailing `()` to make a unit struct or unit enum variant") + .emit(); } } @@ -200,10 +219,10 @@ impl<'a> Visitor for AstValidator<'a> { fn visit_vis(&mut self, vis: &Visibility) { match *vis { - Visibility::Restricted{ref path, ..} => { + Visibility::Restricted { ref path, .. } => { if !path.segments.iter().all(|segment| segment.parameters.is_empty()) { - self.err_handler().span_err(path.span, "type or lifetime parameters \ - in visibility path"); + self.err_handler() + .span_err(path.span, "type or lifetime parameters in visibility path"); } } _ => {} diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 1030a4b0116..fc55118c9f4 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -25,7 +25,7 @@ // by borrowck::gather_loans use rustc::dep_graph::DepNode; -use rustc::ty::cast::{CastKind}; +use rustc::ty::cast::CastKind; use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs}; use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; @@ -71,12 +71,12 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mode: Mode, qualif: ConstQualif, - rvalue_borrows: NodeMap<hir::Mutability> + rvalue_borrows: NodeMap<hir::Mutability>, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { - fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where - F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R, + fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R + where F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R { let (old_mode, old_qualif) = (self.mode, self.qualif); self.mode = mode; @@ -87,17 +87,17 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { r } - fn with_euv<F, R>(&mut self, item_id: Option<ast::NodeId>, f: F) -> R where - F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R, + fn with_euv<F, R>(&mut self, item_id: Option<ast::NodeId>, f: F) -> R + where F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R { let param_env = match item_id { Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id), - None => self.tcx.empty_parameter_environment() + None => self.tcx.empty_parameter_environment(), }; - self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal).enter(|infcx| { - f(&mut euv::ExprUseVisitor::new(self, &infcx)) - }) + self.tcx + .infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal) + .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx))) } fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif { @@ -111,13 +111,17 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) { match err.kind { - UnimplementedConstVal(_) => {}, - IndexOpFeatureGated => {}, - ErroneousReferencedConstant(_) => {}, - _ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span, - format!("constant evaluation error: {}. This will \ - become a HARD ERROR in the future", - err.description().into_oneline())), + UnimplementedConstVal(_) => {} + IndexOpFeatureGated => {} + ErroneousReferencedConstant(_) => {} + _ => { + self.tcx.sess.add_lint(CONST_ERR, + expr.id, + expr.span, + format!("constant evaluation error: {}. This will \ + become a HARD ERROR in the future", + err.description().into_oneline())) + } } } self.with_mode(mode, |this| { @@ -143,9 +147,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } let mode = match fk { - FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => { - Mode::ConstFn - } + FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => Mode::ConstFn, FnKind::Method(_, m, _, _) => { if m.constness == hir::Constness::Const { Mode::ConstFn @@ -153,7 +155,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { Mode::Var } } - _ => Mode::Var + _ => Mode::Var, }; let qualif = self.with_mode(mode, |this| { @@ -175,11 +177,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } /// Returns true if the call is to a const fn or method. - fn handle_const_fn_call(&mut self, - _expr: &hir::Expr, - def_id: DefId, - ret_ty: Ty<'gcx>) - -> bool { + fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, ret_ty: Ty<'gcx>) -> bool { if let Some(fn_like) = lookup_const_fn_by_id(self.tcx, def_id) { let qualif = self.fn_like(fn_like.kind(), fn_like.decl(), @@ -285,13 +283,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { Ok(Ordering::Less) | Ok(Ordering::Equal) => {} Ok(Ordering::Greater) => { - span_err!(self.tcx.sess, start.span, E0030, - "lower range bound must be less than or equal to upper"); + span_err!(self.tcx.sess, + start.span, + E0030, + "lower range bound must be less than or equal to upper"); } Err(ErrorReported) => {} } } - _ => intravisit::walk_pat(self, p) + _ => intravisit::walk_pat(self, p), } } @@ -301,13 +301,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { match stmt.node { hir::StmtDecl(ref decl, _) => { match decl.node { - hir::DeclLocal(_) => {}, + hir::DeclLocal(_) => {} // Item statements are allowed - hir::DeclItem(_) => continue + hir::DeclItem(_) => continue, } } - hir::StmtExpr(_, _) => {}, - hir::StmtSemi(_, _) => {}, + hir::StmtExpr(_, _) => {} + hir::StmtSemi(_, _) => {} } self.add_qualif(ConstQualif::NOT_CONST); } @@ -340,7 +340,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { // The count is checked elsewhere (typeck). let count = match node_ty.sty { ty::TyArray(_, n) => n, - _ => bug!() + _ => bug!(), }; // [element; 0] is always zero-sized. if count == 0 { @@ -354,7 +354,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { for pat in arms.iter().flat_map(|arm| &arm.pats) { let pat_borrow = self.rvalue_borrows.remove(&pat.id); match (borrow, pat_borrow) { - (None, _) | (_, Some(hir::MutMutable)) => { + (None, _) | + (_, Some(hir::MutMutable)) => { borrow = pat_borrow; } _ => {} @@ -365,7 +366,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { } intravisit::walk_expr(self, ex); } - _ => intravisit::walk_expr(self, ex) + _ => intravisit::walk_expr(self, ex), } // Handle borrows on (or inside the autorefs of) this expression. @@ -405,17 +406,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { if self.mode == Mode::Var && !self.qualif.intersects(ConstQualif::NOT_CONST) { match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) { Ok(_) => {} - Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) | - Err(ConstEvalErr { kind: MiscCatchAll, ..}) | - Err(ConstEvalErr { kind: MiscBinaryOp, ..}) | - Err(ConstEvalErr { kind: NonConstPath, ..}) | - Err(ConstEvalErr { kind: UnresolvedPath, ..}) | - Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), ..}) | - Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), ..}) | - Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), ..}) | - Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {}, + Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) | + Err(ConstEvalErr { kind: MiscCatchAll, .. }) | + Err(ConstEvalErr { kind: MiscBinaryOp, .. }) | + Err(ConstEvalErr { kind: NonConstPath, .. }) | + Err(ConstEvalErr { kind: UnresolvedPath, .. }) | + Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), .. }) | + Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), .. }) | + Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), .. }) | + Err(ConstEvalErr { kind: IndexOpFeatureGated, .. }) => {} Err(msg) => { - self.tcx.sess.add_lint(CONST_ERR, ex.id, + self.tcx.sess.add_lint(CONST_ERR, + ex.id, msg.span, msg.description().into_oneline().into_owned()) } @@ -434,8 +436,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { /// every nested expression. If the expression is not part /// of a const/static item, it is qualified for promotion /// instead of producing errors. -fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, - e: &hir::Expr, node_ty: Ty<'tcx>) { +fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) { match node_ty.sty { ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { @@ -635,12 +636,9 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp Some(&ty::adjustment::AdjustUnsafeFnPointer) | Some(&ty::adjustment::AdjustMutToConstPointer) => {} - Some(&ty::adjustment::AdjustDerefRef( - ty::adjustment::AutoDerefRef { autoderefs, .. } - )) => { - if (0..autoderefs as u32).any(|autoderef| { - v.tcx.is_overloaded_autoderef(e.id, autoderef) - }) { + Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef { autoderefs, .. })) => { + if (0..autoderefs as u32) + .any(|autoderef| v.tcx.is_overloaded_autoderef(e.id, autoderef)) { v.add_qualif(ConstQualif::NOT_CONST); } } @@ -648,12 +646,13 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor { - tcx: tcx, - mode: Mode::Var, - qualif: ConstQualif::NOT_CONST, - rvalue_borrows: NodeMap() - }); + tcx.visit_all_items_in_krate(DepNode::CheckConst, + &mut CheckCrateVisitor { + tcx: tcx, + mode: Mode::Var, + qualif: ConstQualif::NOT_CONST, + rvalue_borrows: NodeMap(), + }); tcx.sess.abort_if_errors(); } @@ -675,7 +674,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { Categorization::Rvalue(..) | Categorization::Upvar(..) | - Categorization::Local(..) => break + Categorization::Local(..) => break, } } } @@ -685,8 +684,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { cmt: mc::cmt<'tcx>, _loan_region: ty::Region, bk: ty::BorrowKind, - loan_cause: euv::LoanCause) - { + loan_cause: euv::LoanCause) { // Kind of hacky, but we allow Unsafe coercions in constants. // These occur when we convert a &T or *T to a *U, as well as // when making a thin pointer (e.g., `*T`) into a fat pointer @@ -695,7 +693,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { euv::LoanCause::AutoUnsafe => { return; } - _ => { } + _ => {} } let mut cur = &cmt; @@ -715,7 +713,8 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { // type of the expression. `&mut [1]` has exactly the // same representation as &mut 1. match cmt.ty.sty { - ty::TyArray(_, _) | ty::TySlice(_) => break, + ty::TyArray(_, _) | + ty::TySlice(_) => break, _ => {} } } @@ -732,27 +731,20 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { } Categorization::Upvar(..) | - Categorization::Local(..) => break + Categorization::Local(..) => break, } } } - fn decl_without_init(&mut self, - _id: ast::NodeId, - _span: Span) {} + fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) {} fn mutate(&mut self, _assignment_id: ast::NodeId, _assignment_span: Span, _assignee_cmt: mc::cmt, - _mode: euv::MutateMode) {} + _mode: euv::MutateMode) { + } - fn matched_pat(&mut self, - _: &hir::Pat, - _: mc::cmt, - _: euv::MatchMode) {} + fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::MatchMode) {} - fn consume_pat(&mut self, - _consume_pat: &hir::Pat, - _cmt: mc::cmt, - _mode: euv::ConsumeMode) {} + fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: mc::cmt, _mode: euv::ConsumeMode) {} } diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 3e2dd477bcc..7049040678e 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -121,11 +121,11 @@ All statics and constants need to resolve to a value in an acyclic manner. For example, neither of the following can be sensibly compiled: -```compile_fail +```compile_fail,E0265 const X: u32 = X; ``` -```compile_fail +```compile_fail,E0265 const X: u32 = Y; const Y: u32 = X; ``` @@ -135,7 +135,7 @@ E0267: r##" This error indicates the use of a loop keyword (`break` or `continue`) inside a closure but outside of any loop. Erroneous code example: -```compile_fail +```compile_fail,E0267 let w = || { break; }; // error: `break` inside of a closure ``` @@ -159,7 +159,7 @@ This error indicates the use of a loop keyword (`break` or `continue`) outside of a loop. Without a loop to break out of or continue in, no sensible action can be taken. Erroneous code example: -```compile_fail +```compile_fail,E0268 fn some_func() { break; // error: `break` outside of loop } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 650613f4844..e59c4a6fc41 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -28,12 +28,15 @@ #![feature(rustc_private)] extern crate core; -#[macro_use] extern crate rustc; +#[macro_use] +extern crate rustc; extern crate rustc_const_eval; extern crate rustc_const_math; -#[macro_use] extern crate log; -#[macro_use] extern crate syntax; +#[macro_use] +extern crate log; +#[macro_use] +extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index dd0f16baaa3..4e251793f69 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -19,19 +19,24 @@ use syntax_pos::Span; #[derive(Clone, Copy, PartialEq)] enum Context { - Normal, Loop, Closure + Normal, + Loop, + Closure, } #[derive(Copy, Clone)] struct CheckLoopVisitor<'a> { sess: &'a Session, - cx: Context + cx: Context, } pub fn check_crate(sess: &Session, map: &Map) { let _task = map.dep_graph.in_task(DepNode::CheckLoops); let krate = map.krate(); - krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal }); + krate.visit_all_items(&mut CheckLoopVisitor { + sess: sess, + cx: Normal, + }); } impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { @@ -53,14 +58,14 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { } hir::ExprBreak(_) => self.require_loop("break", e.span), hir::ExprAgain(_) => self.require_loop("continue", e.span), - _ => intravisit::walk_expr(self, e) + _ => intravisit::walk_expr(self, e), } } } impl<'a> CheckLoopVisitor<'a> { - fn with_context<F>(&mut self, cx: Context, f: F) where - F: FnOnce(&mut CheckLoopVisitor<'a>), + fn with_context<F>(&mut self, cx: Context, f: F) + where F: FnOnce(&mut CheckLoopVisitor<'a>) { let old_cx = self.cx; self.cx = cx; @@ -72,12 +77,10 @@ impl<'a> CheckLoopVisitor<'a> { match self.cx { Loop => {} Closure => { - span_err!(self.sess, span, E0267, - "`{}` inside of a closure", name); + span_err!(self.sess, span, E0267, "`{}` inside of a closure", name); } Normal => { - span_err!(self.sess, span, E0268, - "`{}` outside of loop", name); + span_err!(self.sess, span, E0268, "`{}` outside of loop", name); } } } diff --git a/src/librustc_passes/no_asm.rs b/src/librustc_passes/no_asm.rs index 314513a974e..af3065d64e8 100644 --- a/src/librustc_passes/no_asm.rs +++ b/src/librustc_passes/no_asm.rs @@ -19,9 +19,11 @@ use syntax::visit::Visitor; use syntax::visit; pub fn check_crate(sess: &Session, krate: &ast::Crate) { - if sess.target.target.options.allow_asm { return; } + if sess.target.target.options.allow_asm { + return; + } - visit::walk_crate(&mut CheckNoAsm { sess: sess, }, krate); + visit::walk_crate(&mut CheckNoAsm { sess: sess }, krate); } #[derive(Copy, Clone)] @@ -32,9 +34,13 @@ struct CheckNoAsm<'a> { impl<'a> Visitor for CheckNoAsm<'a> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprKind::InlineAsm(_) => span_err!(self.sess, e.span, E0472, - "asm! is unsupported on this target"), - _ => {}, + ast::ExprKind::InlineAsm(_) => { + span_err!(self.sess, + e.span, + E0472, + "asm! is unsupported on this target") + } + _ => {} } visit::walk_expr(self, e) } diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index d0938ad09a0..8b2943a33c0 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -13,11 +13,11 @@ use rustc::dep_graph::DepNode; use rustc::hir::map as ast_map; -use rustc::session::{Session, CompileResult}; +use rustc::session::{CompileResult, Session}; use rustc::hir::def::{Def, DefMap}; use rustc::util::nodemap::NodeMap; -use syntax::{ast}; +use syntax::ast; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax_pos::Span; use rustc::hir::intravisit::{self, Visitor}; @@ -41,18 +41,17 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> { match it.node { hir::ItemStatic(..) | hir::ItemConst(..) => { - let mut recursion_visitor = - CheckItemRecursionVisitor::new(self, &it.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &it.span); recursion_visitor.visit_item(it); - }, + } hir::ItemEnum(ref enum_def, ref generics) => { // We could process the whole enum, but handling the variants // with discriminant expressions one by one gives more specific, // less redundant output. for variant in &enum_def.variants { if let Some(_) = variant.node.disr_expr { - let mut recursion_visitor = - CheckItemRecursionVisitor::new(self, &variant.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self, + &variant.span); recursion_visitor.populate_enum_discriminants(enum_def); recursion_visitor.visit_variant(variant, generics, it.id); } @@ -67,8 +66,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> { match ti.node { hir::ConstTraitItem(_, ref default) => { if let Some(_) = *default { - let mut recursion_visitor = - CheckItemRecursionVisitor::new(self, &ti.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span); recursion_visitor.visit_trait_item(ti); } } @@ -80,8 +78,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> { fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { match ii.node { hir::ImplItemKind::Const(..) => { - let mut recursion_visitor = - CheckItemRecursionVisitor::new(self, &ii.span); + let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ii.span); recursion_visitor.visit_impl_item(ii); } _ => {} @@ -117,7 +114,8 @@ struct CheckItemRecursionVisitor<'a, 'ast: 'a> { } impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> { - fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span) + fn new(v: &'a CheckCrateVisitor<'a, 'ast>, + span: &'a Span) -> CheckItemRecursionVisitor<'a, 'ast> { CheckItemRecursionVisitor { root_span: span, @@ -129,7 +127,8 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> { } } fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F) - where F: Fn(&mut Self) { + where F: Fn(&mut Self) + { if self.idstack.iter().any(|&x| x == id) { let any_static = self.idstack.iter().any(|&x| { if let ast_map::NodeItem(item) = self.ast_map.get(x) { @@ -146,7 +145,9 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> { if !self.sess.features.borrow().static_recursion { emit_feature_err(&self.sess.parse_sess.span_diagnostic, "static_recursion", - *self.root_span, GateIssue::Language, "recursive static"); + *self.root_span, + GateIssue::Language, + "recursive static"); } } else { span_err!(self.sess, *self.root_span, E0265, "recursive constant"); @@ -170,7 +171,9 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> { // has no variants. let mut discriminant_map = self.discriminant_map.borrow_mut(); match enum_definition.variants.first() { - None => { return; } + None => { + return; + } Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => { return; } @@ -203,14 +206,19 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it)); } - fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef, - generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) { + fn visit_enum_def(&mut self, + enum_definition: &'ast hir::EnumDef, + generics: &'ast hir::Generics, + item_id: ast::NodeId, + _: Span) { self.populate_enum_discriminants(enum_definition); intravisit::walk_enum_def(self, enum_definition, generics, item_id); } - fn visit_variant(&mut self, variant: &'ast hir::Variant, - _: &'ast hir::Generics, _: ast::NodeId) { + fn visit_variant(&mut self, + variant: &'ast hir::Variant, + _: &'ast hir::Generics, + _: ast::NodeId) { let variant_id = variant.node.data.id(); let maybe_expr; if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) { @@ -246,18 +254,14 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { Some(Def::Const(def_id)) => { if let Some(node_id) = self.ast_map.as_local_node_id(def_id) { match self.ast_map.get(node_id) { - ast_map::NodeItem(item) => - self.visit_item(item), - ast_map::NodeTraitItem(item) => - self.visit_trait_item(item), - ast_map::NodeImplItem(item) => - self.visit_impl_item(item), - ast_map::NodeForeignItem(_) => {}, + ast_map::NodeItem(item) => self.visit_item(item), + ast_map::NodeTraitItem(item) => self.visit_trait_item(item), + ast_map::NodeImplItem(item) => self.visit_impl_item(item), + ast_map::NodeForeignItem(_) => {} _ => { - span_bug!( - e.span, - "expected item, found {}", - self.ast_map.node_to_string(node_id)); + span_bug!(e.span, + "expected item, found {}", + self.ast_map.node_to_string(node_id)); } } } @@ -268,9 +272,9 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { // might be (if any). Some(Def::Variant(enum_id, variant_id)) => { if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) { - if let hir::ItemEnum(ref enum_def, ref generics) = - self.ast_map.expect_item(enum_node_id).node - { + if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map + .expect_item(enum_node_id) + .node { self.populate_enum_discriminants(enum_def); let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap(); let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap(); @@ -283,10 +287,10 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { } } } - _ => () + _ => (), } - }, - _ => () + } + _ => (), } intravisit::walk_expr(self, e); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5867e48c7ca..116c1b7a6d0 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,7 +16,7 @@ use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; use Module; use Namespace::{self, TypeNS, ValueNS}; -use {NameBinding, NameBindingKind}; +use {NameBinding, NameBindingKind, ToNameBinding}; use ParentLink::{ModuleParentLink, BlockParentLink}; use Resolver; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -39,10 +39,6 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; -trait ToNameBinding<'a> { - fn to_name_binding(self) -> NameBinding<'a>; -} - impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) { fn to_name_binding(self) -> NameBinding<'a> { NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 } @@ -68,18 +64,13 @@ impl<'b> Resolver<'b> { visit::walk_crate(&mut visitor, krate); } - /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined. - fn try_define<T>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) - where T: ToNameBinding<'b> - { - let _ = parent.try_define_child(name, ns, def.to_name_binding()); - } - /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) { + fn define<T>(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T) + where T: ToNameBinding<'b>, + { let binding = def.to_name_binding(); - if let Err(old_binding) = parent.try_define_child(name, ns, binding.clone()) { + if let Err(old_binding) = self.try_define(parent, name, ns, binding.clone()) { self.report_conflict(parent, name, ns, old_binding, &binding); } } @@ -399,14 +390,14 @@ impl<'b> Resolver<'b> { name, vis); let parent_link = ModuleParentLink(parent, name); let module = self.new_module(parent_link, Some(def), true); - self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); } Def::Variant(_, variant_id) => { debug!("(building reduced graph for external crate) building variant {}", name); // Variants are always treated as importable to allow them to be glob used. // All variants are defined in both type and value namespaces as future-proofing. - self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); - self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) { // Not adding fields for variants as they are not accessed with a self receiver self.structs.insert(variant_id, Vec::new()); @@ -419,7 +410,7 @@ impl<'b> Resolver<'b> { Def::Method(..) => { debug!("(building reduced graph for external crate) building value (fn/static) {}", name); - self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); } Def::Trait(def_id) => { debug!("(building reduced graph for external crate) building type {}", name); @@ -441,20 +432,20 @@ impl<'b> Resolver<'b> { let parent_link = ModuleParentLink(parent, name); let module = self.new_module(parent_link, Some(def), true); - self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); } Def::TyAlias(..) | Def::AssociatedTy(..) => { debug!("(building reduced graph for external crate) building type {}", name); - self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); } Def::Struct(def_id) if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => { debug!("(building reduced graph for external crate) building type and value for {}", name); - self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) { let def = Def::Struct(ctor_def_id); - self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); } // Record the def ID and fields of this struct. diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3e860150a35..11ef75ee6a8 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -146,6 +146,7 @@ mod foo { } use foo::MyTrait::do_something; +// error: `do_something` is not directly importable fn main() {} ``` @@ -153,6 +154,45 @@ fn main() {} It's invalid to directly import methods belonging to a trait or concrete type. "##, +E0254: r##" +Attempt was made to import an item whereas an extern crate with this name has +already been imported. + +Erroneous code example: + +```compile_fail,E0254 +extern crate collections; + +mod foo { + pub trait collections { + fn do_something(); + } +} + +use foo::collections; // error: an extern crate named `collections` has already + // been imported in this module + +fn main() {} +``` + +To fix issue issue, you have to rename at least one of the two imports. +Example: + +```ignore +extern crate collections as libcollections; // ok! + +mod foo { + pub trait collections { + fn do_something(); + } +} + +use foo::collections; + +fn main() {} +``` +"##, + E0255: r##" You can't import a value whose name is the same as another value defined in the module. @@ -1237,7 +1277,6 @@ impl Foo for i32 {} register_diagnostics! { // E0153, unused error code // E0157, unused error code - E0254, // import conflicts with imported crate in this module // E0257, // E0258, E0402, // cannot use an outer type parameter in this context diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c1511b29c9e..befe3285911 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -158,7 +158,7 @@ enum ResolutionError<'a> { /// error E0435: attempt to use a non-constant value in a constant AttemptToUseNonConstantValueInConstant, /// error E0530: X bindings cannot shadow Ys - BindingShadowsSomethingUnacceptable(&'a str, &'a str, Name), + BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>), /// error E0531: unresolved pattern path kind `name` PatPathUnresolved(&'a str, &'a Path), /// error E0532: expected pattern path kind, found another pattern path kind @@ -219,7 +219,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, name) } ResolutionError::IsNotATrait(name) => { - struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name) + let mut err = struct_span_err!(resolver.session, + span, + E0404, + "`{}` is not a trait", + name); + err.span_label(span, &format!("not a trait")); + err } ResolutionError::UndeclaredTraitName(name, candidates) => { let mut err = struct_span_err!(resolver.session, @@ -422,17 +428,16 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, E0435, "attempt to use a non-constant value in a constant") } - ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, shadows_what, name) => { + ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { + let shadows_what = PathResolution::new(binding.def().unwrap()).kind_name(); let mut err = struct_span_err!(resolver.session, span, E0530, "{}s cannot shadow {}s", what_binding, shadows_what); err.span_label(span, &format!("cannot be named the same as a {}", shadows_what)); - if let Success(binding) = resolver.current_module.resolve_name(name, ValueNS, true) { - let participle = if binding.is_import() { "imported" } else { "defined" }; - err.span_label(binding.span, &format!("a {} `{}` is {} here", - shadows_what, name, participle)); - } + let participle = if binding.is_import() { "imported" } else { "defined" }; + let msg = &format!("a {} `{}` is {} here", shadows_what, name, participle); + err.span_label(binding.span, msg); err } ResolutionError::PatPathUnresolved(expected_what, path) => { @@ -712,12 +717,16 @@ impl<'a> LexicalScopeBinding<'a> { } } - fn module(self) -> Option<Module<'a>> { + fn item(self) -> Option<&'a NameBinding<'a>> { match self { - LexicalScopeBinding::Item(binding) => binding.module(), + LexicalScopeBinding::Item(binding) => Some(binding), _ => None, } } + + fn module(self) -> Option<Module<'a>> { + self.item().and_then(NameBinding::module) + } } /// The link from a module up to its nearest parent node. @@ -818,6 +827,16 @@ pub struct NameBinding<'a> { vis: ty::Visibility, } +pub trait ToNameBinding<'a> { + fn to_name_binding(self) -> NameBinding<'a>; +} + +impl<'a> ToNameBinding<'a> for NameBinding<'a> { + fn to_name_binding(self) -> NameBinding<'a> { + self + } +} + #[derive(Clone, Debug)] enum NameBindingKind<'a> { Def(Def), @@ -1197,34 +1216,27 @@ impl<'a> Resolver<'a> { match ns { ValueNS => &mut self.value_ribs, TypeNS => &mut self.type_ribs } } - #[inline] - fn record_use(&mut self, name: Name, binding: &'a NameBinding<'a>) { + fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) { // track extern crates for unused_extern_crate lint if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) { self.used_crates.insert(krate); } - let directive = match binding.kind { - NameBindingKind::Import { directive, .. } => directive, - _ => return, - }; - - if !self.make_glob_map { - return; - } - if self.glob_map.contains_key(&directive.id) { - self.glob_map.get_mut(&directive.id).unwrap().insert(name); - return; + if let NameBindingKind::Import { directive, .. } = binding.kind { + self.used_imports.insert((directive.id, ns)); + self.add_to_glob_map(directive.id, name); } + } - let mut new_set = FnvHashSet(); - new_set.insert(name); - self.glob_map.insert(directive.id, new_set); + fn add_to_glob_map(&mut self, id: NodeId, name: Name) { + if self.make_glob_map { + self.glob_map.entry(id).or_insert_with(FnvHashSet).insert(name); + } } - /// Resolves the given module path from the given root `module_`. + /// Resolves the given module path from the given root `search_module`. fn resolve_module_path_from_root(&mut self, - module_: Module<'a>, + mut search_module: Module<'a>, module_path: &[Name], index: usize, span: Span) @@ -1241,7 +1253,6 @@ impl<'a> Resolver<'a> { } } - let mut search_module = module_; let mut index = index; let module_path_len = module_path.len(); @@ -1438,10 +1449,9 @@ impl<'a> Resolver<'a> { } /// Returns the nearest normal module parent of the given module. - fn get_nearest_normal_module_parent(&self, module_: Module<'a>) -> Option<Module<'a>> { - let mut module_ = module_; + fn get_nearest_normal_module_parent(&self, mut module: Module<'a>) -> Option<Module<'a>> { loop { - match module_.parent_link { + match module.parent_link { NoParentLink => return None, ModuleParentLink(new_module, _) | BlockParentLink(new_module, _) => { @@ -1449,7 +1459,7 @@ impl<'a> Resolver<'a> { if new_module.is_normal() { return Some(new_module); } - module_ = new_module; + module = new_module; } } } @@ -1457,12 +1467,12 @@ impl<'a> Resolver<'a> { /// Returns the nearest normal module parent of the given module, or the /// module itself if it is a normal module. - fn get_nearest_normal_module_parent_or_self(&self, module_: Module<'a>) -> Module<'a> { - if module_.is_normal() { - return module_; + fn get_nearest_normal_module_parent_or_self(&self, module: Module<'a>) -> Module<'a> { + if module.is_normal() { + return module; } - match self.get_nearest_normal_module_parent(module_) { - None => module_, + match self.get_nearest_normal_module_parent(module) { + None => module, Some(new_module) => new_module, } } @@ -1479,8 +1489,8 @@ impl<'a> Resolver<'a> { "super" => 0, _ => return Success(NoPrefixFound), }; - let module_ = self.current_module; - let mut containing_module = self.get_nearest_normal_module_parent_or_self(module_); + let mut containing_module = + self.get_nearest_normal_module_parent_or_self(self.current_module); // Now loop through all the `super`s we find. while i < module_path.len() && "super" == module_path[i].as_str() { @@ -1519,10 +1529,7 @@ impl<'a> Resolver<'a> { self.populate_module_if_necessary(module); module.resolve_name(name, namespace, use_lexical_scope).and_then(|binding| { if record_used { - if let NameBindingKind::Import { directive, .. } = binding.kind { - self.used_imports.insert((directive.id, namespace)); - } - self.record_use(name, binding); + self.record_use(name, namespace, binding); } Success(binding) }) @@ -2302,16 +2309,17 @@ impl<'a> Resolver<'a> { PatKind::Ident(bmode, ref ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let resolution = self.resolve_identifier(ident.node, ValueNS, true) - .map(|local_def| PathResolution::new(local_def.def)) - .and_then(|resolution| { + let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, false) + .and_then(LexicalScopeBinding::item); + let resolution = binding.and_then(NameBinding::def).and_then(|def| { let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || bmode != BindingMode::ByValue(Mutability::Immutable); - match resolution.base_def { + match def { Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { // A constant, unit variant, etc pattern. - Some(resolution) + self.record_use(ident.node.name, ValueNS, binding.unwrap()); + Some(PathResolution::new(def)) } Def::Struct(..) | Def::Variant(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { @@ -2320,7 +2328,7 @@ impl<'a> Resolver<'a> { self, ident.span, ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), resolution.kind_name(), ident.node.name) + pat_src.descr(), ident.node.name, binding.unwrap()) ); None } @@ -3130,10 +3138,10 @@ impl<'a> Resolver<'a> { if let NameBindingKind::Import { directive, .. } = binding.kind { let id = directive.id; this.maybe_unused_trait_imports.insert(id); + this.add_to_glob_map(id, trait_name); import_id = Some(id); } add_trait_info(&mut found_traits, trait_def_id, import_id, name); - this.record_use(trait_name, binding); } } }; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index fc5e2a48e87..6986f99926e 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -12,7 +12,7 @@ use self::ImportDirectiveSubclass::*; use Module; use Namespace::{self, TypeNS, ValueNS}; -use {NameBinding, NameBindingKind, PrivacyError}; +use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}; use ResolveResult; use ResolveResult::*; use Resolver; @@ -21,7 +21,7 @@ use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use rustc::ty; -use rustc::lint; +use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def::*; use syntax::ast::{NodeId, Name}; @@ -71,19 +71,6 @@ pub struct ImportDirective<'a> { } impl<'a> ImportDirective<'a> { - // Given the binding to which this directive resolves in a particular namespace, - // this returns the binding for the name this directive defines in that namespace. - fn import(&'a self, binding: &'a NameBinding<'a>) -> NameBinding<'a> { - NameBinding { - kind: NameBindingKind::Import { - binding: binding, - directive: self, - }, - span: self.span, - vis: self.vis, - } - } - pub fn is_glob(&self) -> bool { match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false } } @@ -137,23 +124,6 @@ impl<'a> SingleImports<'a> { } impl<'a> NameResolution<'a> { - fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> { - if let Some(old_binding) = self.binding { - if binding.is_glob_import() { - self.duplicate_globs.push(binding); - } else if old_binding.is_glob_import() { - self.duplicate_globs.push(old_binding); - self.binding = Some(binding); - } else { - return Err(old_binding); - } - } else { - self.binding = Some(binding); - } - - Ok(()) - } - // Returns the binding for the name if it is known or None if it not known. fn binding(&self) -> Option<&'a NameBinding<'a>> { self.binding.and_then(|binding| match self.single_imports { @@ -203,24 +173,6 @@ impl<'a> NameResolution<'a> { self.binding.map(Success) } - - fn report_conflicts<F: FnMut(&NameBinding, &NameBinding)>(&self, mut report: F) { - let binding = match self.binding { - Some(binding) => binding, - None => return, - }; - - for duplicate_glob in self.duplicate_globs.iter() { - // FIXME #31337: We currently allow items to shadow glob-imported re-exports. - if !binding.is_import() { - if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind { - if binding.is_import() { continue } - } - } - - report(duplicate_glob, binding); - } - } } impl<'a> ::ModuleS<'a> { @@ -261,14 +213,6 @@ impl<'a> ::ModuleS<'a> { Failed(None) } - // Define the name or return the existing binding if there is a collision. - pub fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) - -> Result<(), &'a NameBinding<'a>> { - self.update_resolution(name, ns, |resolution| { - resolution.try_define(self.arenas.alloc_name_binding(binding)) - }) - } - pub fn add_import_directive(&self, module_path: Vec<Name>, subclass: ImportDirectiveSubclass, @@ -298,19 +242,59 @@ impl<'a> ::ModuleS<'a> { GlobImport { .. } => self.globs.borrow_mut().push(directive), } } +} + +impl<'a> Resolver<'a> { + // Given a binding and an import directive that resolves to it, + // return the corresponding binding defined by the import directive. + fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>) + -> NameBinding<'a> { + NameBinding { + kind: NameBindingKind::Import { + binding: binding, + directive: directive, + }, + span: directive.span, + vis: directive.vis, + } + } - // Use `update` to mutate the resolution for the name. + // Define the name or return the existing binding if there is a collision. + pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, binding: T) + -> Result<(), &'a NameBinding<'a>> + where T: ToNameBinding<'a> + { + let binding = self.arenas.alloc_name_binding(binding.to_name_binding()); + self.update_resolution(module, name, ns, |_, resolution| { + if let Some(old_binding) = resolution.binding { + if binding.is_glob_import() { + resolution.duplicate_globs.push(binding); + } else if old_binding.is_glob_import() { + resolution.duplicate_globs.push(old_binding); + resolution.binding = Some(binding); + } else { + return Err(old_binding); + } + } else { + resolution.binding = Some(binding); + } + + Ok(()) + }) + } + + // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T - where F: FnOnce(&mut NameResolution<'a>) -> T + fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T + where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T { - // Ensure that `resolution` isn't borrowed during `define_in_glob_importers`, - // where it might end up getting re-defined via a glob cycle. + // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, + // during which the resolution might end up getting re-defined via a glob cycle. let (new_binding, t) = { - let mut resolution = &mut *self.resolution(name, ns).borrow_mut(); + let mut resolution = &mut *module.resolution(name, ns).borrow_mut(); let was_known = resolution.binding().is_some(); - let t = update(resolution); + let t = f(self, resolution); if was_known { return t; } match resolution.binding() { @@ -319,15 +303,15 @@ impl<'a> ::ModuleS<'a> { } }; - self.define_in_glob_importers(name, ns, new_binding); - t - } - - fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) { - if !binding.is_importable() || !binding.is_pseudo_public() { return } - for &(importer, directive) in self.glob_importers.borrow_mut().iter() { - let _ = importer.try_define_child(name, ns, directive.import(binding)); + // Define `new_binding` in `module`s glob importers. + if new_binding.is_importable() && new_binding.is_pseudo_public() { + for &(importer, directive) in module.glob_importers.borrow_mut().iter() { + let imported_binding = self.import(new_binding, directive); + let _ = self.try_define(importer, name, ns, imported_binding); + } } + + t } } @@ -343,6 +327,25 @@ struct ImportResolver<'a, 'b: 'a> { resolver: &'a mut Resolver<'b>, } +impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { + type Target = Resolver<'b>; + fn deref(&self) -> &Resolver<'b> { + self.resolver + } +} + +impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> { + fn deref_mut(&mut self) -> &mut Resolver<'b> { + self.resolver + } +} + +impl<'a, 'b: 'a> ty::NodeIdTree for ImportResolver<'a, 'b> { + fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool { + self.resolver.is_descendant_of(node, ancestor) + } +} + impl<'a, 'b:'a> ImportResolver<'a, 'b> { // Import resolution // @@ -360,31 +363,29 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let mut errors = Vec::new(); loop { - debug!("(resolving imports) iteration {}, {} imports left", - i, - self.resolver.unresolved_imports); + debug!("(resolving imports) iteration {}, {} imports left", i, self.unresolved_imports); // Attempt to resolve imports in all local modules. - for module in self.resolver.arenas.local_modules().iter() { - self.resolver.current_module = module; + for module in self.arenas.local_modules().iter() { + self.current_module = module; self.resolve_imports_in_current_module(&mut errors); } - if self.resolver.unresolved_imports == 0 { + if self.unresolved_imports == 0 { debug!("(resolving imports) success"); - for module in self.resolver.arenas.local_modules().iter() { + for module in self.arenas.local_modules().iter() { self.finalize_resolutions_in(module, false); } break; } - if self.resolver.unresolved_imports == prev_unresolved_imports { + if self.unresolved_imports == prev_unresolved_imports { // resolving failed // Report unresolved imports only if no hard error was already reported // to avoid generating multiple errors on the same import. // Imports that are still indeterminate at this point are actually blocked // by errored imports, so there is no point reporting them. - for module in self.resolver.arenas.local_modules().iter() { + for module in self.arenas.local_modules().iter() { self.finalize_resolutions_in(module, errors.len() == 0); } for e in errors { @@ -394,29 +395,31 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } i += 1; - prev_unresolved_imports = self.resolver.unresolved_imports; + prev_unresolved_imports = self.unresolved_imports; } } // Define a "dummy" resolution containing a Def::Err as a placeholder for a // failed resolution - fn import_dummy_binding(&self, source_module: Module<'b>, directive: &'b ImportDirective<'b>) { + fn import_dummy_binding(&mut self, + source_module: Module<'b>, + directive: &'b ImportDirective<'b>) { if let SingleImport { target, .. } = directive.subclass { - let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding { + let dummy_binding = self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Err), span: DUMMY_SP, vis: ty::Visibility::Public, }); - let dummy_binding = directive.import(dummy_binding); + let dummy_binding = self.import(dummy_binding, directive); - let _ = source_module.try_define_child(target, ValueNS, dummy_binding.clone()); - let _ = source_module.try_define_child(target, TypeNS, dummy_binding); + let _ = self.try_define(source_module, target, ValueNS, dummy_binding.clone()); + let _ = self.try_define(source_module, target, TypeNS, dummy_binding); } } /// Resolves an `ImportResolvingError` into the correct enum discriminant /// and passes that on to `resolve_error`. - fn import_resolving_error(&self, e: ImportResolvingError<'b>) { + fn import_resolving_error(&mut self, e: ImportResolvingError<'b>) { // If the error is a single failed import then create a "fake" import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(e.source_module, e.import_directive); @@ -430,7 +433,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { /// Attempts to resolve imports for the given module only. fn resolve_imports_in_current_module(&mut self, errors: &mut Vec<ImportResolvingError<'b>>) { let mut imports = Vec::new(); - let mut unresolved_imports = self.resolver.current_module.unresolved_imports.borrow_mut(); + let mut unresolved_imports = self.current_module.unresolved_imports.borrow_mut(); ::std::mem::swap(&mut imports, &mut unresolved_imports); for import_directive in imports { @@ -441,7 +444,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => (import_directive.span, String::new()), }; errors.push(ImportResolvingError { - source_module: self.resolver.current_module, + source_module: self.current_module, import_directive: import_directive, span: span, help: help, @@ -450,8 +453,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { Indeterminate => unresolved_imports.push(import_directive), Success(()) => { // Decrement the count of unresolved imports. - assert!(self.resolver.unresolved_imports >= 1); - self.resolver.unresolved_imports -= 1; + assert!(self.unresolved_imports >= 1); + self.unresolved_imports -= 1; } } } @@ -465,13 +468,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> { debug!("(resolving import for module) resolving import `{}::...` in `{}`", names_to_string(&directive.module_path), - module_to_string(self.resolver.current_module)); + module_to_string(self.current_module)); let target_module = match directive.target_module.get() { Some(module) => module, - _ => match self.resolver.resolve_module_path(&directive.module_path, - DontUseLexicalScope, - directive.span) { + _ => match self.resolve_module_path(&directive.module_path, + DontUseLexicalScope, + directive.span) { Success(module) => module, Indeterminate => return Indeterminate, Failed(err) => return Failed(err), @@ -486,38 +489,36 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; // We need to resolve both namespaces for this to succeed. - let value_result = - self.resolver.resolve_name_in_module(target_module, source, ValueNS, false, true); - let type_result = - self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true); + let value_result = self.resolve_name_in_module(target_module, source, ValueNS, false, true); + let type_result = self.resolve_name_in_module(target_module, source, TypeNS, false, true); - let module_ = self.resolver.current_module; + let module = self.current_module; let mut privacy_error = true; for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined), (TypeNS, &type_result, type_determined)] { match *result { Failed(..) if !determined.get() => { determined.set(true); - module_.update_resolution(target, ns, |resolution| { + self.update_resolution(module, target, ns, |_, resolution| { resolution.single_imports.directive_failed() }); } Success(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); - span_err!(self.resolver.session, directive.span, E0253, "{}", &msg); + span_err!(self.session, directive.span, E0253, "{}", &msg); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine - self.import_dummy_binding(module_, directive); + self.import_dummy_binding(module, directive); return Success(()); } - Success(binding) if !self.resolver.is_accessible(binding.vis) => {} + Success(binding) if !self.is_accessible(binding.vis) => {} Success(binding) if !determined.get() => { determined.set(true); - let imported_binding = directive.import(binding); - let conflict = module_.try_define_child(target, ns, imported_binding); + let imported_binding = self.import(binding, directive); + let conflict = self.try_define(module, target, ns, imported_binding); if let Err(old_binding) = conflict { - let binding = &directive.import(binding); - self.resolver.report_conflict(module_, target, ns, binding, old_binding); + let binding = &self.import(binding, directive); + self.report_conflict(module, target, ns, binding, old_binding); } privacy_error = false; } @@ -556,39 +557,35 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if privacy_error { for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] { let binding = match *result { Success(binding) => binding, _ => continue }; - self.resolver.privacy_errors.push(PrivacyError(directive.span, source, binding)); - let _ = module_.try_define_child(target, ns, directive.import(binding)); + self.privacy_errors.push(PrivacyError(directive.span, source, binding)); + let imported_binding = self.import(binding, directive); + let _ = self.try_define(module, target, ns, imported_binding); } } match (&value_result, &type_result) { - (&Success(binding), _) if !binding.pseudo_vis() - .is_at_least(directive.vis, self.resolver) && - self.resolver.is_accessible(binding.vis) => { + (&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, self) && + self.is_accessible(binding.vis) => { let msg = format!("`{}` is private, and cannot be reexported", source); let note_msg = format!("consider marking `{}` as `pub` in the imported module", source); - struct_span_err!(self.resolver.session, directive.span, E0364, "{}", &msg) + struct_span_err!(self.session, directive.span, E0364, "{}", &msg) .span_note(directive.span, ¬e_msg) .emit(); } - (_, &Success(binding)) if !binding.pseudo_vis() - .is_at_least(directive.vis, self.resolver) && - self.resolver.is_accessible(binding.vis) => { + (_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, self) && + self.is_accessible(binding.vis) => { if binding.is_extern_crate() { let msg = format!("extern crate `{}` is private, and cannot be reexported \ (error E0364), consider declaring with `pub`", source); - self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, - directive.id, - directive.span, - msg); + self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); } else { let msg = format!("`{}` is private, and cannot be reexported", source); let note_msg = format!("consider declaring type or module `{}` with `pub`", source); - struct_span_err!(self.resolver.session, directive.span, E0365, "{}", &msg) + struct_span_err!(self.session, directive.span, E0365, "{}", &msg) .span_note(directive.span, ¬e_msg) .emit(); } @@ -605,7 +602,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => value_result.success().and_then(NameBinding::def).unwrap(), }; let path_resolution = PathResolution::new(def); - self.resolver.def_map.insert(directive.id, path_resolution); + self.def_map.insert(directive.id, path_resolution); debug!("(resolving single import) successfully resolved import"); return Success(()); @@ -618,40 +615,41 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>) -> ResolveResult<()> { if let Some(Def::Trait(_)) = target_module.def { - self.resolver.session.span_err(directive.span, "items in traits are not importable."); + self.session.span_err(directive.span, "items in traits are not importable."); } - let module_ = self.resolver.current_module; - if module_.def_id() == target_module.def_id() { + let module = self.current_module; + if module.def_id() == target_module.def_id() { // This means we are trying to glob import a module into itself, and it is a no-go let msg = "Cannot glob-import a module into itself.".into(); return Failed(Some((directive.span, msg))); } - self.resolver.populate_module_if_necessary(target_module); + self.populate_module_if_necessary(target_module); if let GlobImport { is_prelude: true } = directive.subclass { - self.resolver.prelude = Some(target_module); + self.prelude = Some(target_module); return Success(()); } // Add to target_module's glob_importers - target_module.glob_importers.borrow_mut().push((module_, directive)); + target_module.glob_importers.borrow_mut().push((module, directive)); - // Ensure that `resolutions` isn't borrowed during `try_define_child`, + // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. let bindings = target_module.resolutions.borrow().iter().filter_map(|(name, resolution)| { resolution.borrow().binding().map(|binding| (*name, binding)) }).collect::<Vec<_>>(); for ((name, ns), binding) in bindings { if binding.is_importable() && binding.is_pseudo_public() { - let _ = module_.try_define_child(name, ns, directive.import(binding)); + let imported_binding = self.import(binding, directive); + let _ = self.try_define(module, name, ns, imported_binding); } } // Record the destination of this import if let Some(did) = target_module.def_id() { let resolution = PathResolution::new(Def::Mod(did)); - self.resolver.def_map.insert(directive.id, resolution); + self.def_map.insert(directive.id, resolution); } debug!("(resolving glob import) successfully resolved import"); @@ -667,15 +665,23 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); for (&(name, ns), resolution) in module.resolutions.borrow().iter() { let resolution = resolution.borrow(); - resolution.report_conflicts(|b1, b2| { - self.resolver.report_conflict(module, name, ns, b1, b2) - }); - let binding = match resolution.binding { Some(binding) => binding, None => continue, }; + // Report conflicts + for duplicate_glob in resolution.duplicate_globs.iter() { + // FIXME #31337: We currently allow items to shadow glob-imported re-exports. + if !binding.is_import() { + if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind { + if binding.is_import() { continue } + } + } + + self.report_conflict(module, name, ns, duplicate_glob, binding); + } + if binding.vis == ty::Visibility::Public && (binding.is_import() || binding.is_extern_crate()) { if let Some(def) = binding.def() { @@ -685,20 +691,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { if ns == TypeNS && orig_binding.is_variant() && - !orig_binding.vis.is_at_least(binding.vis, self.resolver) { + !orig_binding.vis.is_at_least(binding.vis, self) { let msg = format!("variant `{}` is private, and cannot be reexported \ (error E0364), consider declaring its enum as `pub`", name); - let lint = lint::builtin::PRIVATE_IN_PUBLIC; - self.resolver.session.add_lint(lint, directive.id, binding.span, msg); + self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg); } } } if reexports.len() > 0 { if let Some(def_id) = module.def_id() { - let node_id = self.resolver.definitions.as_local_node_id(def_id).unwrap(); - self.resolver.export_map.insert(node_id, reexports); + let node_id = self.definitions.as_local_node_id(def_id).unwrap(); + self.export_map.insert(node_id, reexports); } } diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 464c32c3cc7..f2c7068565e 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -18,7 +18,7 @@ use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit}; use self::namespace::mangled_name_of_item; use self::type_names::compute_debuginfo_type_name; use self::metadata::{type_metadata, diverging_type_metadata}; -use self::metadata::{file_metadata, scope_metadata, TypeMap}; +use self::metadata::{file_metadata, TypeMap}; use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 2f27aed065d..4980fad0cc3 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -406,9 +406,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_str_slice(ccx, ty_name) } (_, "type_id") => { - let hash = ccx.tcx().hash_crate_independent(*substs.types.get(FnSpace, 0), - &ccx.link_meta().crate_hash); - C_u64(ccx, hash) + C_u64(ccx, ccx.tcx().type_id_hash(*substs.types.get(FnSpace, 0))) } (_, "init_dropped") => { let tp_ty = *substs.types.get(FnSpace, 0); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3b2bca4ab39..50ffa52e88b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -310,8 +310,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { None => match rscope.anon_regions(default_span, 1) { Ok(rs) => rs[0], Err(params) => { - let mut err = struct_span_err!(self.tcx().sess, default_span, E0106, - "missing lifetime specifier"); + let ampersand_span = Span { hi: default_span.lo, ..default_span}; + + let mut err = struct_span_err!(self.tcx().sess, ampersand_span, E0106, + "missing lifetime specifier"); + err.span_label(ampersand_span, &format!("expected lifetime parameter")); + if let Some(params) = params { report_elision_failure(&mut err, params); } @@ -1075,8 +1079,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Ok((trait_ref, projection_bounds)) } _ => { - span_err!(self.tcx().sess, ty.span, E0172, - "expected a reference to a trait"); + struct_span_err!(self.tcx().sess, ty.span, E0172, + "expected a reference to a trait") + .span_label(ty.span, &format!("expected a trait")) + .emit(); Err(ErrorReported) } } @@ -1086,6 +1092,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "expected a path on the left-hand side \ of `+`, not `{}`", pprust::ty_to_string(ty)); + err.span_label(ty.span, &format!("expected a path")); let hi = bounds.iter().map(|x| match *x { hir::TraitTyParamBound(ref tr, _) => tr.span.hi, hir::RegionTyParamBound(ref r) => r.span.hi, @@ -2266,9 +2273,25 @@ fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, } fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) { - span_err!(tcx.sess, span, E0107, - "wrong number of lifetime parameters: expected {}, found {}", - expected, number); + let label = if number < expected { + if expected == 1 { + format!("expected {} lifetime parameter", expected) + } else { + format!("expected {} lifetime parameters", expected) + } + } else { + let additional = number - expected; + if additional == 1 { + "unexpected lifetime parameter".to_string() + } else { + format!("{} unexpected lifetime parameters", additional) + } + }; + struct_span_err!(tcx.sess, span, E0107, + "wrong number of lifetime parameters: expected {}, found {}", + expected, number) + .span_label(span, &label) + .emit(); } // A helper struct for conveniently grouping a set of bounds which we pass to diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 3c176744fca..265422468fe 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -54,9 +54,11 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { if self.steps.len() == tcx.sess.recursion_limit.get() { // We've reached the recursion limit, error gracefully. - span_err!(tcx.sess, self.span, E0055, + struct_span_err!(tcx.sess, self.span, E0055, "reached the recursion limit while auto-dereferencing {:?}", - self.cur_ty); + self.cur_ty) + .span_label(self.span, &format!("deref recursion limit reached")) + .emit(); return None; } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6062bd048b3..8da06120873 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -847,7 +847,9 @@ fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // good } hir::Constness::Const => { - span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const"); + struct_span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const") + .span_label(span, &format!("trait fns cannot be const")) + .emit() } } } @@ -993,7 +995,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Check existing impl methods to see if they are both present in trait // and compatible with trait signature for impl_item in impl_items { - let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id)); + let ty_impl_item = tcx.impl_or_trait_item(tcx.map.local_def_id(impl_item.id)); let ty_trait_item = trait_items.iter() .find(|ac| ac.name() == ty_impl_item.name()); @@ -1014,11 +1016,18 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_const, &impl_trait_ref); } else { - span_err!(tcx.sess, impl_item.span, E0323, + let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323, "item `{}` is an associated const, \ which doesn't match its trait `{:?}`", impl_const.name, - impl_trait_ref) + impl_trait_ref); + err.span_label(impl_item.span, &format!("does not match trait")); + // We can only get the spans from local trait definition + // Same for E0324 and E0325 + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + err.span_label(trait_span, &format!("original trait requirement")); + } + err.emit() } } hir::ImplItemKind::Method(ref sig, ref body) => { @@ -1037,11 +1046,16 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &trait_method, &impl_trait_ref); } else { - span_err!(tcx.sess, impl_item.span, E0324, + let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324, "item `{}` is an associated method, \ which doesn't match its trait `{:?}`", impl_method.name, - impl_trait_ref) + impl_trait_ref); + err.span_label(impl_item.span, &format!("does not match trait")); + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + err.span_label(trait_span, &format!("original trait requirement")); + } + err.emit() } } hir::ImplItemKind::Type(_) => { @@ -1055,11 +1069,16 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, overridden_associated_type = Some(impl_item); } } else { - span_err!(tcx.sess, impl_item.span, E0325, + let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325, "item `{}` is an associated type, \ which doesn't match its trait `{:?}`", impl_type.name, - impl_trait_ref) + impl_trait_ref); + err.span_label(impl_item.span, &format!("does not match trait")); + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + err.span_label(trait_span, &format!("original trait requirement")); + } + err.emit() } } } @@ -1251,8 +1270,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0081, "discriminant value `{}` already exists", disr_vals[i]); let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap(); - span_note!(&mut err, ccx.tcx.map.span(variant_i_node_id), - "conflicting discriminant here"); + err.span_label(ccx.tcx.map.span(variant_i_node_id), + &format!("first use of `{}`", disr_vals[i])); + err.span_label(v.span , &format!("enum already has `{}`", disr_vals[i])); err.emit(); } disr_vals.push(current_disr_val); @@ -2384,6 +2404,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { arg_count, if arg_count == 1 {" was"} else {"s were"}), error_code); + + err.span_label(sp, &format!("expected {}{} parameter{}", + if variadic {"at least "} else {""}, + expected_count, + if expected_count == 1 {""} else {"s"})); + let input_types = fn_inputs.iter().map(|i| format!("{:?}", i)).collect::<Vec<String>>(); if input_types.len() > 0 { err.note(&format!("the following parameter type{} expected: {}", @@ -3063,6 +3089,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { remaining_fields.insert(field.name, field); } + let mut seen_fields = FnvHashMap(); + let mut error_happened = false; // Typecheck each field. @@ -3071,13 +3099,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(v_field) = remaining_fields.remove(&field.name.node) { expected_field_type = self.field_ty(field.span, v_field, substs); + + seen_fields.insert(field.name.node, field.span); } else { error_happened = true; expected_field_type = tcx.types.err; if let Some(_) = variant.find_field_named(field.name.node) { - span_err!(self.tcx.sess, field.name.span, E0062, - "field `{}` specified more than once", - field.name.node); + let mut err = struct_span_err!(self.tcx.sess, + field.name.span, + E0062, + "field `{}` specified more than once", + field.name.node); + + err.span_label(field.name.span, &format!("used more than once")); + + if let Some(prev_span) = seen_fields.get(&field.name.node) { + err.span_label(*prev_span, &format!("first use of `{}`", field.name.node)); + } + + err.emit(); } else { self.report_unknown_field(adt_ty, variant, field, ast_fields); } @@ -3147,9 +3187,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple { // Reject tuple structs for now, braced and unit structs are allowed. - span_err!(self.tcx.sess, span, E0071, - "`{}` does not name a struct or a struct variant", - pprust::path_to_string(path)); + struct_span_err!(self.tcx.sess, path.span, E0071, + "`{}` does not name a struct or a struct variant", + pprust::path_to_string(path)) + .span_label(path.span, &format!("not a struct")) + .emit(); + return None; } @@ -3383,8 +3426,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // FIXME(#32730) propagate obligations .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())); if eq_result.is_err() { - span_err!(tcx.sess, expr.span, E0069, - "`return;` in a function whose return type is not `()`"); + struct_span_err!(tcx.sess, expr.span, E0069, + "`return;` in a function whose return type is not `()`") + .span_label(expr.span, &format!("return type is not ()")) + .emit(); } } } @@ -3392,8 +3437,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(ref e) = *expr_opt { self.check_expr(&e); } - span_err!(tcx.sess, expr.span, E0166, - "`return` in a function declared as diverging"); + struct_span_err!(tcx.sess, expr.span, E0166, + "`return` in a function declared as diverging") + .span_label(expr.span, &format!("diverging function cannot return")) + .emit(); } } self.write_ty(id, self.next_diverging_ty_var()); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d02f87d0b9c..63487683ec3 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -176,11 +176,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // error types are considered "builtin" if !lhs_ty.references_error() { if let IsAssign::Yes = is_assign { - span_err!(self.tcx.sess, lhs_expr.span, E0368, - "binary assignment operation `{}=` \ - cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty); + struct_span_err!(self.tcx.sess, lhs_expr.span, E0368, + "binary assignment operation `{}=` \ + cannot be applied to type `{}`", + op.node.as_str(), + lhs_ty) + .span_label(lhs_expr.span, + &format!("cannot use `{}=` on type `{}`", + op.node.as_str(), lhs_ty)) + .emit(); } else { let mut err = struct_span_err!(self.tcx.sess, lhs_expr.span, E0369, "binary operation `{}` cannot be applied to type `{}`", diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 198e9afd5e1..2d14b0dacf2 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -249,8 +249,17 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) { match tcx.map.find(impl_node_id) { Some(hir_map::NodeItem(item)) => { - span_err!(tcx.sess, item.span, E0120, - "the Drop trait may only be implemented on structures"); + let span = match item.node { + ItemImpl(_, _, _, _, ref ty, _) => { + ty.span + }, + _ => item.span + }; + struct_span_err!(tcx.sess, span, E0120, + "the Drop trait may only be implemented on structures") + .span_label(span, + &format!("implementing Drop requires a struct")) + .emit(); } _ => { bug!("didn't find impl in ast map"); @@ -258,7 +267,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } } else { bug!("found external impl of Drop trait on \ - :omething other than a struct"); + something other than a struct"); } } } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index dcaa5cfb20a..54bd141304d 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -141,12 +141,18 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0119, "conflicting implementations of trait `{}`{}:", overlap.trait_desc, - overlap.self_desc.map_or(String::new(), - |ty| format!(" for type `{}`", ty))); + overlap.self_desc.clone().map_or(String::new(), + |ty| format!(" for type `{}`", ty))); match self.tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - err.span_note(span, "conflicting implementation is here:"); + err.span_label(span, + &format!("first implementation here")); + err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(), + &format!("conflicting implementation{}", + overlap.self_desc + .map_or(String::new(), + |ty| format!(" for `{}`", ty)))); } Err(cname) => { err.note(&format!("conflicting implementation in crate `{}`", diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4486748a1f0..92b91028b98 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -184,6 +184,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { let mut err = struct_span_err!(tcx.sess, span, E0391, "unsupported cyclic reference between types/traits detected"); + err.span_label(span, &format!("cyclic reference")); match cycle[0] { AstConvRequest::GetItemTypeScheme(def_id) | @@ -1010,11 +1011,12 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fid = ccx.tcx.map.local_def_id(f.id); let dup_span = seen_fields.get(&f.name).cloned(); if let Some(prev_span) = dup_span { - let mut err = struct_span_err!(ccx.tcx.sess, f.span, E0124, - "field `{}` is already declared", - f.name); - span_note!(&mut err, prev_span, "previously declared here"); - err.emit(); + struct_span_err!(ccx.tcx.sess, f.span, E0124, + "field `{}` is already declared", + f.name) + .span_label(f.span, &"field already declared") + .span_label(prev_span, &format!("`{}` first declared here", f.name)) + .emit(); } else { seen_fields.insert(f.name, f.span); } @@ -1057,6 +1059,7 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let print_err = |cv: ConstVal| { struct_span_err!(ccx.tcx.sess, e.span, E0079, "mismatched types") .note_expected_found(&"type", &ty_hint, &format!("{}", cv.description())) + .span_label(e.span, &format!("expected '{}' type", ty_hint)) .emit(); }; @@ -2314,8 +2317,12 @@ fn report_unused_parameter(ccx: &CrateCtxt, kind: &str, name: &str) { - span_err!(ccx.tcx.sess, span, E0207, - "the {} parameter `{}` is not constrained by the \ - impl trait, self type, or predicates", - kind, name); + struct_span_err!( + ccx.tcx.sess, span, E0207, + "the {} parameter `{}` is not constrained by the \ + impl trait, self type, or predicates", + kind, name) + .span_label(span, &format!("unconstrained lifetime parameter")) + .emit(); + } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index b655d955429..64b27857d2c 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3864,6 +3864,104 @@ impl SpaceLlama for i32 { ``` "##, +E0527: r##" +The number of elements in an array or slice pattern differed from the number of +elements in the array being matched. + +Example of erroneous code: + +```compile_fail,E0527 +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4]; +match r { + &[a, b] => { // error: pattern requires 2 elements but array + // has 4 + println!("a={}, b={}", a, b); + } +} +``` + +Ensure that the pattern is consistent with the size of the matched +array. Additional elements can be matched with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4]; +match r { + &[a, b, ..] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` +"##, + +E0528: r##" +An array or slice pattern required more elements than were present in the +matched array. + +Example of erroneous code: + +```compile_fail,E0528 +#![feature(slice_patterns)] + +let r = &[1, 2]; +match r { + &[a, b, c, rest..] => { // error: pattern requires at least 3 + // elements but array has 2 + println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); + } +} +``` + +Ensure that the matched array has at least as many elements as the pattern +requires. You can match an arbitrary number of remaining elements with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4, 5]; +match r { + &[a, b, c, rest..] => { // ok! + // prints `a=1, b=2, c=3 rest=[4, 5]` + println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); + } +} +``` +"##, + +E0529: r##" +An array or slice pattern was matched against some other type. + +Example of erroneous code: + +```compile_fail,E0529 +#![feature(slice_patterns)] + +let r: f32 = 1.0; +match r { + [a, b] => { // error: expected an array or slice, found `f32` + println!("a={}, b={}", a, b); + } +} +``` + +Ensure that the pattern and the expression being matched on are of consistent +types: + +``` +#![feature(slice_patterns)] + +let r = [1.0, 2.0]; +match r { + [a, b] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` +"##, + E0559: r##" An unknown field was specified into an enum's structure variant. @@ -3985,8 +4083,5 @@ register_diagnostics! { E0436, // functional record update requires a struct E0513, // no type for local variable .. E0521, // redundant default implementations of trait - E0527, // expected {} elements, found {} - E0528, // expected at least {} elements, found {} - E0529, // slice pattern expects array or slice, not `{}` E0533, // `{}` does not name a unit variant, unit struct or a constant } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 3b2d02dc861..6f0892cdcdf 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -261,8 +261,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt, match it.node { hir::ItemFn(_,_,_,_,ref ps,_) if ps.is_parameterized() => { - span_err!(tcx.sess, start_span, E0132, - "start function is not allowed to have type parameters"); + struct_span_err!(tcx.sess, start_span, E0132, + "start function is not allowed to have type parameters") + .span_label(ps.span().unwrap(), + &format!("start function cannot have type parameters")) + .emit(); return; } _ => () diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 0d3e18f9b96..f800a6e228e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -356,6 +356,18 @@ impl Borrow<CStr> for CString { impl NulError { /// Returns the position of the nul byte in the slice that was provided to /// `CString::new`. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let nul_error = CString::new("foo\0bar").unwrap_err(); + /// assert_eq!(nul_error.nul_position(), 3); + /// + /// let nul_error = CString::new("foo bar\0").unwrap_err(); + /// assert_eq!(nul_error.nul_position(), 7); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn nul_position(&self) -> usize { self.0 } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 38fd93501a5..b78db24e44b 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -156,7 +156,10 @@ pub struct OpenOptions(fs_imp::OpenOptions); #[stable(feature = "rust1", since = "1.0.0")] pub struct Permissions(fs_imp::FilePermissions); -/// An structure representing a type of file with accessors for each file type. +/// A structure representing a type of file with accessors for each file type. +/// It is returned by [`Metadata::file_type`] method. +/// +/// [`Metadata::file_type`]: struct.Metadata.html#method.file_type #[stable(feature = "file_type", since = "1.1.0")] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType(fs_imp::FileType); @@ -610,6 +613,19 @@ impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { impl Metadata { /// Returns the file type for this metadata. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// + /// println!("{:?}", metadata.file_type()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn file_type(&self) -> FileType { FileType(self.0.file_type()) @@ -839,14 +855,56 @@ impl Permissions { impl FileType { /// Test whether this file type represents a directory. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// let file_type = metadata.file_type(); + /// + /// assert_eq!(file_type.is_dir(), false); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Test whether this file type represents a regular file. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// let file_type = metadata.file_type(); + /// + /// assert_eq!(file_type.is_file(), true); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() } /// Test whether this file type represents a symbolic link. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// let file_type = metadata.file_type(); + /// + /// assert_eq!(file_type.is_symlink(), false); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() } } diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 05ae8ed5b0b..5333b0a531e 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -55,7 +55,9 @@ pub type Result<T> = result::Result<T, Error>; /// /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of -/// `ErrorKind`. +/// [`ErrorKind`]. +/// +/// [`ErrorKind`]: enum.ErrorKind.html #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Error { @@ -77,6 +79,10 @@ struct Custom { /// /// This list is intended to grow over time and it is not recommended to /// exhaustively match against it. +/// +/// It is used with the [`io::Error`] type. +/// +/// [`io::Error`]: struct.Error.html #[derive(Copy, PartialEq, Eq, Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -208,6 +214,14 @@ impl Error { /// This function reads the value of `errno` for the target platform (e.g. /// `GetLastError` on Windows) and will return a corresponding instance of /// `Error` for the error code. + /// + /// # Examples + /// + /// ``` + /// use std::io::Error; + /// + /// println!("last OS error: {:?}", Error::last_os_error()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn last_os_error() -> Error { Error::from_raw_os_error(sys::os::errno() as i32) @@ -248,6 +262,27 @@ impl Error { /// If this `Error` was constructed via `last_os_error` or /// `from_raw_os_error`, then this function will return `Some`, otherwise /// it will return `None`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_os_error(err: &Error) { + /// if let Some(raw_os_err) = err.raw_os_error() { + /// println!("raw OS error: {:?}", raw_os_err); + /// } else { + /// println!("Not an OS error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "raw OS error: ...". + /// print_os_error(&Error::last_os_error()); + /// // Will print "Not an OS error". + /// print_os_error(&Error::new(ErrorKind::Other, "oh no!")); + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn raw_os_error(&self) -> Option<i32> { match self.repr { @@ -260,6 +295,27 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: &Error) { + /// if let Some(inner_err) = err.get_ref() { + /// println!("Inner error: {:?}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(&Error::last_os_error()); + /// // Will print "Inner error: ...". + /// print_error(&Error::new(ErrorKind::Other, "oh no!")); + /// } + /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { match self.repr { @@ -273,6 +329,63 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use std::{error, fmt}; + /// use std::fmt::Display; + /// + /// #[derive(Debug)] + /// struct MyError { + /// v: String, + /// } + /// + /// impl MyError { + /// fn new() -> MyError { + /// MyError { + /// v: "oh no!".to_owned() + /// } + /// } + /// + /// fn change_message(&mut self, new_message: &str) { + /// self.v = new_message.to_owned(); + /// } + /// } + /// + /// impl error::Error for MyError { + /// fn description(&self) -> &str { &self.v } + /// } + /// + /// impl Display for MyError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "MyError: {}", &self.v) + /// } + /// } + /// + /// fn change_error(mut err: Error) -> Error { + /// if let Some(inner_err) = err.get_mut() { + /// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!"); + /// } + /// err + /// } + /// + /// fn print_error(err: &Error) { + /// if let Some(inner_err) = err.get_ref() { + /// println!("Inner error: {}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(&change_error(Error::last_os_error())); + /// // Will print "Inner error: ...". + /// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new()))); + /// } + /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { match self.repr { @@ -285,6 +398,27 @@ impl Error { /// /// If this `Error` was constructed via `new` then this function will /// return `Some`, otherwise it will return `None`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// if let Some(inner_err) = err.into_inner() { + /// println!("Inner error: {}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(Error::last_os_error()); + /// // Will print "Inner error: ...". + /// print_error(Error::new(ErrorKind::Other, "oh no!")); + /// } + /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> { match self.repr { @@ -294,6 +428,23 @@ impl Error { } /// Returns the corresponding `ErrorKind` for this error. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// println!("{:?}", err.kind()); + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(Error::last_os_error()); + /// // Will print "Inner error: ...". + /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn kind(&self) -> ErrorKind { match self.repr { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d5b255ee573..88fd4186e0a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1082,16 +1082,22 @@ pub trait Seek { /// /// If the seek operation completed successfully, /// this method returns the new position from the start of the stream. - /// That position can be used later with `SeekFrom::Start`. + /// That position can be used later with [`SeekFrom::Start`]. /// /// # Errors /// /// Seeking to a negative offset is considered an error. + /// + /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start #[stable(feature = "rust1", since = "1.0.0")] fn seek(&mut self, pos: SeekFrom) -> Result<u64>; } /// Enumeration of possible methods to seek within an I/O object. +/// +/// It is used by the [`Seek`] trait. +/// +/// [`Seek`]: trait.Seek.html #[derive(Copy, PartialEq, Eq, Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum SeekFrom { @@ -1482,6 +1488,24 @@ impl<T> Take<T> { /// /// This instance may reach EOF after reading fewer bytes than indicated by /// this method if the underlying `Read` instance reaches EOF. + /// + /// # Examples + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let f = try!(File::open("foo.txt")); + /// + /// // read at most five bytes + /// let handle = f.take(5); + /// + /// println!("limit: {}", handle.limit()); + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index c4b573db5f2..b8b66a58359 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -240,6 +240,21 @@ impl Stdin { /// /// [`Read`]: trait.Read.html /// [`BufRead`]: trait.BufRead.html + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Read}; + /// + /// # fn foo() -> io::Result<String> { + /// let mut buffer = String::new(); + /// let stdin = io::stdin(); + /// let mut handle = stdin.lock(); + /// + /// try!(handle.read_to_string(&mut buffer)); + /// # Ok(buffer) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } @@ -399,6 +414,21 @@ impl Stdout { /// /// The lock is released when the returned lock goes out of scope. The /// returned guard also implements the `Write` trait for writing data. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// + /// # fn foo() -> io::Result<()> { + /// let stdout = io::stdout(); + /// let mut handle = stdout.lock(); + /// + /// try!(handle.write(b"hello world")); + /// + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock { StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } @@ -505,6 +535,21 @@ impl Stderr { /// /// The lock is released when the returned lock goes out of scope. The /// returned guard also implements the `Write` trait for writing data. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// + /// fn foo() -> io::Result<()> { + /// let stderr = io::stderr(); + /// let mut handle = stderr.lock(); + /// + /// try!(handle.write(b"hello world")); + /// + /// Ok(()) + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock { StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index ac13b23ebee..11a16b27113 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -35,7 +35,11 @@ mod udp; mod parser; #[cfg(test)] mod test; -/// Possible values which can be passed to the `shutdown` method of `TcpStream`. +/// Possible values which can be passed to the [`shutdown`] method of +/// [`TcpStream`]. +/// +/// [`shutdown`]: struct.TcpStream.html#method.shutdown +/// [`TcpStream`]: struct.TcpStream.html #[derive(Copy, Clone, PartialEq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Shutdown { diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 5ab0d5a0877..76617f15970 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -77,6 +77,11 @@ pub struct TcpListener(net_imp::TcpListener); /// /// This iterator will infinitely yield `Some` of the accepted connections. It /// is equivalent to calling `accept` in a loop. +/// +/// This `struct` is created by the [`incoming`] method on [`TcpListener`]. +/// +/// [`incoming`]: struct.TcpListener.html#method.incoming +/// [`TcpListener`]: struct.TcpListener.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Incoming<'a> { listener: &'a TcpListener } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index b315e676263..3b132744f70 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -27,7 +27,7 @@ use sys_common::{AsInner, FromInner}; #[cfg(any(target_os = "linux", target_os = "emscripten"))] use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64}; #[cfg(target_os = "android")] -use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off64_t, lseek64, +use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64, dirent as dirent64, open as open64}; #[cfg(not(any(target_os = "linux", target_os = "emscripten", @@ -485,9 +485,11 @@ impl File { pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> { let (whence, pos) = match pos { - SeekFrom::Start(off) => (libc::SEEK_SET, off as off64_t), - SeekFrom::End(off) => (libc::SEEK_END, off as off64_t), - SeekFrom::Current(off) => (libc::SEEK_CUR, off as off64_t), + // Casting to `i64` is fine, too large values will end up as + // negative which will cause an error in `lseek64`. + SeekFrom::Start(off) => (libc::SEEK_SET, off as i64), + SeekFrom::End(off) => (libc::SEEK_END, off), + SeekFrom::Current(off) => (libc::SEEK_CUR, off), }; let n = cvt(unsafe { lseek64(self.0.raw(), pos, whence) })?; Ok(n as u64) diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 2683e57256d..4e6cef9a28d 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -324,6 +324,8 @@ impl File { pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> { let (whence, pos) = match pos { + // Casting to `i64` is fine, `SetFilePointerEx` reinterprets this + // integer as `u64`. SeekFrom::Start(n) => (c::FILE_BEGIN, n as i64), SeekFrom::End(n) => (c::FILE_END, n), SeekFrom::Current(n) => (c::FILE_CURRENT, n), diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index e9736fea7b3..f06c105d30e 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -447,6 +447,8 @@ pub fn park() { *guard = false; } +/// Use [park_timeout]. +/// /// Blocks unless or until the current thread's token is made available or /// the specified duration has been reached (may wake spuriously). /// @@ -456,7 +458,10 @@ pub fn park() { /// preemption or platform differences that may not cause the maximum /// amount of time waited to be precisely `ms` long. /// -/// See the module doc for more detail. +/// See the [module documentation][thread] for more detail. +/// +/// [thread]: index.html +/// [park_timeout]: fn.park_timeout.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")] pub fn park_timeout_ms(ms: u32) { @@ -478,6 +483,25 @@ pub fn park_timeout_ms(ms: u32) { /// /// Platforms which do not support nanosecond precision for sleeping will have /// `dur` rounded up to the nearest granularity of time they can sleep for. +/// +/// # Example +/// +/// Waiting for the complete expiration of the timeout: +/// +/// ```rust,no_run +/// use std::thread::park_timeout; +/// use std::time::{Instant, Duration}; +/// +/// let timeout = Duration::from_secs(2); +/// let beginning_park = Instant::now(); +/// park_timeout(timeout); +/// +/// while beginning_park.elapsed() < timeout { +/// println!("restarting park_timeout after {:?}", beginning_park.elapsed()); +/// let timeout = timeout - beginning_park.elapsed(); +/// park_timeout(timeout); +/// } +/// ``` #[stable(feature = "park_timeout", since = "1.4.0")] pub fn park_timeout(dur: Duration) { let thread = current(); diff --git a/src/test/compile-fail/E0055.rs b/src/test/compile-fail/E0055.rs index f86d7ec114b..2b2d278ad4c 100644 --- a/src/test/compile-fail/E0055.rs +++ b/src/test/compile-fail/E0055.rs @@ -18,5 +18,7 @@ impl Foo { fn main() { let foo = Foo; let ref_foo = &&Foo; - ref_foo.foo(); //~ ERROR E0055 + ref_foo.foo(); + //~^ ERROR E0055 + //~| NOTE deref recursion limit reached } diff --git a/src/test/compile-fail/E0060.rs b/src/test/compile-fail/E0060.rs index b4a28987497..e1f2618c180 100644 --- a/src/test/compile-fail/E0060.rs +++ b/src/test/compile-fail/E0060.rs @@ -13,5 +13,8 @@ extern "C" { } fn main() { - unsafe { printf(); } //~ ERROR E0060 + unsafe { printf(); } + //~^ ERROR E0060 + //~| NOTE expected at least 1 parameter + //~| NOTE the following parameter type was expected } diff --git a/src/test/compile-fail/E0061.rs b/src/test/compile-fail/E0061.rs index 4a8eac2a9e2..ca04b059dc7 100644 --- a/src/test/compile-fail/E0061.rs +++ b/src/test/compile-fail/E0061.rs @@ -11,5 +11,8 @@ fn f(a: u16, b: &str) {} fn main() { - f(0); //~ ERROR E0061 + f(0); + //~^ ERROR E0061 + //~| NOTE expected 2 parameters + //~| NOTE the following parameter types were expected } diff --git a/src/test/compile-fail/E0062.rs b/src/test/compile-fail/E0062.rs index 86ec7db14b5..822d93e52d5 100644 --- a/src/test/compile-fail/E0062.rs +++ b/src/test/compile-fail/E0062.rs @@ -14,7 +14,9 @@ struct Foo { fn main() { let x = Foo { + x: 0, //~ NOTE first use of `x` x: 0, - x: 0, //~ ERROR E0062 + //~^ ERROR E0062 + //~| NOTE used more than once }; } diff --git a/src/test/compile-fail/E0069.rs b/src/test/compile-fail/E0069.rs index d164d863487..00facc91728 100644 --- a/src/test/compile-fail/E0069.rs +++ b/src/test/compile-fail/E0069.rs @@ -9,7 +9,9 @@ // except according to those terms. fn foo() -> u8 { - return; //~ ERROR E0069 + return; + //~^ ERROR `return;` in a function whose return type is not `()` + //~| NOTE return type is not () } fn main() { diff --git a/src/test/compile-fail/E0071.rs b/src/test/compile-fail/E0071.rs index 658c8fb1551..6f0e55efffc 100644 --- a/src/test/compile-fail/E0071.rs +++ b/src/test/compile-fail/E0071.rs @@ -11,6 +11,11 @@ enum Foo { FirstValue(i32) } fn main() { - let u = Foo::FirstValue { value: 0 }; //~ ERROR E0071 - let t = u32 { value: 4 }; //~ ERROR E0071 + let u = Foo::FirstValue { value: 0 }; + //~^ ERROR `Foo::FirstValue` does not name a struct or a struct variant [E0071] + //~| NOTE not a struct + + let t = u32 { value: 4 }; + //~^ ERROR `u32` does not name a struct or a struct variant [E0071] + //~| NOTE not a struct } diff --git a/src/test/compile-fail/E0079.rs b/src/test/compile-fail/E0079.rs index 23957c72ff0..c9b7f549d5a 100644 --- a/src/test/compile-fail/E0079.rs +++ b/src/test/compile-fail/E0079.rs @@ -10,6 +10,7 @@ enum Foo { Q = "32" //~ ERROR E0079 + //~^ expected 'isize' type } fn main() { diff --git a/src/test/compile-fail/E0106.rs b/src/test/compile-fail/E0106.rs index f1cd530863d..dab03f0bccf 100644 --- a/src/test/compile-fail/E0106.rs +++ b/src/test/compile-fail/E0106.rs @@ -9,13 +9,19 @@ // except according to those terms. struct Foo { - x: &bool, //~ ERROR E0106 + x: &bool, + //~^ ERROR E0106 + //~| NOTE expected lifetime parameter } enum Bar { A(u8), - B(&bool), //~ ERROR E0106 + B(&bool), + //~^ ERROR E0106 + //~| NOTE expected lifetime parameter } -type MyStr = &str; //~ ERROR E0106 +type MyStr = &str; + //~^ ERROR E0106 + //~| NOTE expected lifetime parameter fn main() { } diff --git a/src/test/compile-fail/E0107.rs b/src/test/compile-fail/E0107.rs index d27b70865bb..5f333e17c47 100644 --- a/src/test/compile-fail/E0107.rs +++ b/src/test/compile-fail/E0107.rs @@ -9,6 +9,7 @@ // except according to those terms. struct Foo<'a>(&'a str); +struct Buzz<'a, 'b>(&'a str, &'b str); enum Bar { A, @@ -16,9 +17,19 @@ enum Bar { C, } -struct Baz<'a> { - foo: Foo, //~ ERROR E0107 - bar: Bar<'a>, //~ ERROR E0107 +struct Baz<'a, 'b, 'c> { + foo: Foo, + //~^ ERROR E0107 + //~| expected 1 lifetime parameter + buzz: Buzz<'a>, + //~^ ERROR E0107 + //~| expected 2 lifetime parameters + bar: Bar<'a>, + //~^ ERROR E0107 + //~| unexpected lifetime parameter + foo2: Foo<'a, 'b, 'c>, + //~^ ERROR E0107 + //~| 2 unexpected lifetime parameters } fn main() { diff --git a/src/test/compile-fail/E0109.rs b/src/test/compile-fail/E0109.rs index 9fc47842250..2e4cbf86926 100644 --- a/src/test/compile-fail/E0109.rs +++ b/src/test/compile-fail/E0109.rs @@ -9,6 +9,7 @@ // except according to those terms. type X = u32<i32>; //~ ERROR E0109 + //~| NOTE type parameter not allowed fn main() { } diff --git a/src/test/compile-fail/E0110.rs b/src/test/compile-fail/E0110.rs index fd169f4acc5..5a9e7a43de9 100644 --- a/src/test/compile-fail/E0110.rs +++ b/src/test/compile-fail/E0110.rs @@ -9,6 +9,7 @@ // except according to those terms. type X = u32<'static>; //~ ERROR E0110 + //~| NOTE lifetime parameter not allowed on this type fn main() { } diff --git a/src/test/compile-fail/E0119.rs b/src/test/compile-fail/E0119.rs index 9528631b304..56820bcd184 100644 --- a/src/test/compile-fail/E0119.rs +++ b/src/test/compile-fail/E0119.rs @@ -12,7 +12,7 @@ trait MyTrait { fn get(&self) -> usize; } -impl<T> MyTrait for T { +impl<T> MyTrait for T { //~ NOTE first implementation here fn get(&self) -> usize { 0 } } @@ -21,6 +21,7 @@ struct Foo { } impl MyTrait for Foo { //~ ERROR E0119 + //~| NOTE conflicting implementation for `Foo` fn get(&self) -> usize { self.value } } diff --git a/src/test/compile-fail/E0120.rs b/src/test/compile-fail/E0120.rs index de084274f6f..3fdeb753175 100644 --- a/src/test/compile-fail/E0120.rs +++ b/src/test/compile-fail/E0120.rs @@ -10,7 +10,9 @@ trait MyTrait {} -impl Drop for MyTrait { //~ ERROR E0120 +impl Drop for MyTrait { + //~^ ERROR E0120 + //~| NOTE implementing Drop requires a struct fn drop(&mut self) {} } diff --git a/src/test/compile-fail/E0124.rs b/src/test/compile-fail/E0124.rs index 414b19ead62..18c50746106 100644 --- a/src/test/compile-fail/E0124.rs +++ b/src/test/compile-fail/E0124.rs @@ -9,8 +9,10 @@ // except according to those terms. struct Foo { + field1: i32, //~ NOTE `field1` first declared here field1: i32, - field1: i32, //~ ERROR E0124 + //~^ ERROR field `field1` is already declared [E0124] + //~| NOTE field already declared } fn main() { diff --git a/src/test/compile-fail/E0132.rs b/src/test/compile-fail/E0132.rs index ff19a577f90..1a33fb24ca1 100644 --- a/src/test/compile-fail/E0132.rs +++ b/src/test/compile-fail/E0132.rs @@ -12,6 +12,7 @@ #[start] fn f<T>() {} //~ ERROR E0132 + //~| NOTE start function cannot have type parameters fn main() { } diff --git a/src/test/compile-fail/E0137.rs b/src/test/compile-fail/E0137.rs index 695ce7995a9..f45afc9f37b 100644 --- a/src/test/compile-fail/E0137.rs +++ b/src/test/compile-fail/E0137.rs @@ -11,7 +11,9 @@ #![feature(main)] #[main] -fn foo() {} +fn foo() {} //~ NOTE first #[main] function #[main] -fn f() {} //~ ERROR E0137 +fn f() {} +//~^ ERROR E0137 +//~| NOTE additional #[main] function diff --git a/src/test/compile-fail/E0166.rs b/src/test/compile-fail/E0166.rs index 9fa41249aa5..f8585d71b40 100644 --- a/src/test/compile-fail/E0166.rs +++ b/src/test/compile-fail/E0166.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo() -> ! { return; } //~ ERROR E0166 +fn foo() -> ! { return; } + //~^ ERROR E0166 + //~| NOTE diverging function cannot return fn main() { } diff --git a/src/test/compile-fail/E0172.rs b/src/test/compile-fail/E0172.rs index 7011bf0e937..485a31d9666 100644 --- a/src/test/compile-fail/E0172.rs +++ b/src/test/compile-fail/E0172.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(bar: i32+std::fmt::Display) {} //~ ERROR E0172 +fn foo(bar: i32+std::fmt::Display) {} + //~^ ERROR E0172 + //~| NOTE expected a trait fn main() { } diff --git a/src/test/compile-fail/E0178.rs b/src/test/compile-fail/E0178.rs index f34f3834e05..6527465e0b7 100644 --- a/src/test/compile-fail/E0178.rs +++ b/src/test/compile-fail/E0178.rs @@ -11,10 +11,18 @@ trait Foo {} struct Bar<'a> { - w: &'a Foo + Copy, //~ ERROR E0178 - x: &'a Foo + 'a, //~ ERROR E0178 - y: &'a mut Foo + 'a, //~ ERROR E0178 - z: fn() -> Foo + 'a, //~ ERROR E0178 + w: &'a Foo + Copy, + //~^ ERROR E0178 + //~| NOTE expected a path + x: &'a Foo + 'a, + //~^ ERROR E0178 + //~| NOTE expected a path + y: &'a mut Foo + 'a, + //~^ ERROR E0178 + //~| NOTE expected a path + z: fn() -> Foo + 'a, + //~^ ERROR E0178 + //~| NOTE expected a path } fn main() { diff --git a/src/test/compile-fail/E0207.rs b/src/test/compile-fail/E0207.rs index bd87dbaf786..43ff085a4fa 100644 --- a/src/test/compile-fail/E0207.rs +++ b/src/test/compile-fail/E0207.rs @@ -11,6 +11,7 @@ struct Foo; impl<T: Default> Foo { //~ ERROR E0207 + //~| NOTE unconstrained lifetime parameter fn get(&self) -> T { <T as Default>::default() } diff --git a/src/test/compile-fail/E0229.rs b/src/test/compile-fail/E0229.rs index 45d5c59592f..6ff0baeeb4d 100644 --- a/src/test/compile-fail/E0229.rs +++ b/src/test/compile-fail/E0229.rs @@ -20,7 +20,9 @@ impl Foo for isize { fn boo(&self) -> usize { 42 } } -fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} //~ ERROR E0229 +fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} +//~^ ERROR associated type bindings are not allowed here [E0229] +//~| NOTE associate type not allowed here fn main() { } diff --git a/src/test/compile-fail/E0253.rs b/src/test/compile-fail/E0253.rs new file mode 100644 index 00000000000..28fcf4452b3 --- /dev/null +++ b/src/test/compile-fail/E0253.rs @@ -0,0 +1,19 @@ +// 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. + +mod foo { + pub trait MyTrait { + fn do_something(); + } +} + +use foo::MyTrait::do_something; //~ ERROR E0253 + +fn main() {} diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs new file mode 100644 index 00000000000..28f9aea9657 --- /dev/null +++ b/src/test/compile-fail/E0254.rs @@ -0,0 +1,21 @@ +// 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. + +extern crate collections; + +mod foo { + pub trait collections { + fn do_something(); + } +} + +use foo::collections; //~ ERROR E0254 + +fn main() {} diff --git a/src/test/compile-fail/E0255.rs b/src/test/compile-fail/E0255.rs new file mode 100644 index 00000000000..e05c6bede7e --- /dev/null +++ b/src/test/compile-fail/E0255.rs @@ -0,0 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use bar::foo; + +fn foo() {} //~ ERROR E0255 + +mod bar { + pub fn foo() {} +} + +fn main() {} diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs new file mode 100644 index 00000000000..6b7e8613859 --- /dev/null +++ b/src/test/compile-fail/E0259.rs @@ -0,0 +1,14 @@ +// 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. + +extern crate collections; +extern crate libc as collections; //~ ERROR E0259 + +fn main() {} diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs new file mode 100644 index 00000000000..d20829bf4d4 --- /dev/null +++ b/src/test/compile-fail/E0260.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate collections; + +mod collections { //~ ERROR E0260 + pub trait MyTrait { + fn do_something(); + } +} + +fn main() {} diff --git a/src/test/compile-fail/E0261.rs b/src/test/compile-fail/E0261.rs new file mode 100644 index 00000000000..4196ad370b8 --- /dev/null +++ b/src/test/compile-fail/E0261.rs @@ -0,0 +1,17 @@ +// 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. + +fn foo(x: &'a str) { } //~ ERROR E0261 + +struct Foo { + x: &'a str, //~ ERROR E0261 +} + +fn main() {} diff --git a/src/test/compile-fail/E0262.rs b/src/test/compile-fail/E0262.rs new file mode 100644 index 00000000000..e09e4766d51 --- /dev/null +++ b/src/test/compile-fail/E0262.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn foo<'static>(x: &'static str) { } //~ ERROR E0262 + +fn main() {} diff --git a/src/test/compile-fail/E0263.rs b/src/test/compile-fail/E0263.rs new file mode 100644 index 00000000000..09f654c368c --- /dev/null +++ b/src/test/compile-fail/E0263.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } //~ ERROR E0263 + +fn main() {} diff --git a/src/test/compile-fail/E0264.rs b/src/test/compile-fail/E0264.rs new file mode 100644 index 00000000000..92332977e76 --- /dev/null +++ b/src/test/compile-fail/E0264.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(lang_items)] + +extern "C" { + #[lang = "cake"] + fn cake(); //~ ERROR E0264 +} + +fn main() {} diff --git a/src/test/compile-fail/E0267.rs b/src/test/compile-fail/E0267.rs new file mode 100644 index 00000000000..6287256e866 --- /dev/null +++ b/src/test/compile-fail/E0267.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn main() { + let w = || { break; }; //~ ERROR E0267 +} diff --git a/src/test/compile-fail/E0268.rs b/src/test/compile-fail/E0268.rs new file mode 100644 index 00000000000..41e88e2f492 --- /dev/null +++ b/src/test/compile-fail/E0268.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn main() { + break; //~ ERROR E0268 +} diff --git a/src/test/compile-fail/E0271.rs b/src/test/compile-fail/E0271.rs new file mode 100644 index 00000000000..d322c8b1caf --- /dev/null +++ b/src/test/compile-fail/E0271.rs @@ -0,0 +1,21 @@ +// 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. + +trait Trait { type AssociatedType; } + +fn foo<T>(t: T) where T: Trait<AssociatedType=u32> { + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } + +fn main() { + foo(3_i8); //~ ERROR E0271 +} diff --git a/src/test/compile-fail/E0275.rs b/src/test/compile-fail/E0275.rs new file mode 100644 index 00000000000..8dfd1d9b4af --- /dev/null +++ b/src/test/compile-fail/E0275.rs @@ -0,0 +1,18 @@ +// 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. + +trait Foo {} + +struct Bar<T>(T); + +impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275 + +fn main() { +} diff --git a/src/test/compile-fail/E0276.rs b/src/test/compile-fail/E0276.rs new file mode 100644 index 00000000000..62e43b02ca8 --- /dev/null +++ b/src/test/compile-fail/E0276.rs @@ -0,0 +1,20 @@ +// 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. + +trait Foo { + fn foo<T>(x: T); +} + +impl Foo for bool { + fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0277.rs b/src/test/compile-fail/E0277.rs new file mode 100644 index 00000000000..7737f12ac37 --- /dev/null +++ b/src/test/compile-fail/E0277.rs @@ -0,0 +1,21 @@ +// 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. + +trait Foo { + fn bar(&self); +} + +fn some_func<T: Foo>(foo: T) { + foo.bar(); +} + +fn main() { + some_func(5i32); //~ ERROR E0277 +} diff --git a/src/test/compile-fail/E0281.rs b/src/test/compile-fail/E0281.rs new file mode 100644 index 00000000000..d468cd3ff1b --- /dev/null +++ b/src/test/compile-fail/E0281.rs @@ -0,0 +1,16 @@ +// 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. + +fn foo<F: Fn()>(x: F) { } + +fn main() { + foo(|y| { }); //~ ERROR E0281 + //~^ ERROR E0281 +} diff --git a/src/test/compile-fail/E0282.rs b/src/test/compile-fail/E0282.rs new file mode 100644 index 00000000000..dfc702670ce --- /dev/null +++ b/src/test/compile-fail/E0282.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn main() { + let x = "hello".chars().rev().collect(); //~ ERROR E0282 +} diff --git a/src/test/compile-fail/E0283.rs b/src/test/compile-fail/E0283.rs new file mode 100644 index 00000000000..844c47f41b8 --- /dev/null +++ b/src/test/compile-fail/E0283.rs @@ -0,0 +1,29 @@ +// 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. + +trait Generator { + fn create() -> u32; +} + +struct Impl; + +impl Generator for Impl { + fn create() -> u32 { 1 } +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let cont: u32 = Generator::create(); //~ ERROR E0283 +} diff --git a/src/test/compile-fail/E0296.rs b/src/test/compile-fail/E0296.rs new file mode 100644 index 00000000000..562fd00a18a --- /dev/null +++ b/src/test/compile-fail/E0296.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +#![recursion_limit] //~ ERROR E0296 + +fn main() {} diff --git a/src/test/compile-fail/E0297.rs b/src/test/compile-fail/E0297.rs new file mode 100644 index 00000000000..43166c1a9e8 --- /dev/null +++ b/src/test/compile-fail/E0297.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +fn main() { + let xs : Vec<Option<i32>> = vec!(Some(1), None); + + for Some(x) in xs {} //~ ERROR E0297 +} diff --git a/src/test/compile-fail/E0301.rs b/src/test/compile-fail/E0301.rs new file mode 100644 index 00000000000..06e98289b0d --- /dev/null +++ b/src/test/compile-fail/E0301.rs @@ -0,0 +1,17 @@ +// 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. + +fn main() { + match Some(()) { + None => { }, + option if option.take().is_none() => {}, //~ ERROR E0301 + Some(_) => { } + } +} diff --git a/src/test/compile-fail/E0302.rs b/src/test/compile-fail/E0302.rs new file mode 100644 index 00000000000..6a5ad40b109 --- /dev/null +++ b/src/test/compile-fail/E0302.rs @@ -0,0 +1,17 @@ +// 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. + +fn main() { + match Some(()) { + None => { }, + option if { option = None; false } => { }, //~ ERROR E0302 + Some(_) => { } + } +} diff --git a/src/test/compile-fail/E0303.rs b/src/test/compile-fail/E0303.rs new file mode 100644 index 00000000000..67947fd087c --- /dev/null +++ b/src/test/compile-fail/E0303.rs @@ -0,0 +1,17 @@ +// 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. + +fn main() { + match Some("hi".to_string()) { + ref op_string_ref @ Some(s) => {}, //~ ERROR E0303 + //~^ ERROR E0009 + None => {}, + } +} diff --git a/src/test/compile-fail/E0306.rs b/src/test/compile-fail/E0306.rs index 61cc8902036..9ffaef7472b 100644 --- a/src/test/compile-fail/E0306.rs +++ b/src/test/compile-fail/E0306.rs @@ -8,9 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const A: [u32; "hello"] = []; //~ ERROR E0306 -const B: [u32; true] = []; //~ ERROR E0306 -const C: [u32; 0.0] = []; //~ ERROR E0306 +const A: [u32; "hello"] = []; +//~^ ERROR expected `usize` for array length, found string literal [E0306] +//~| NOTE expected `usize` + +const B: [u32; true] = []; +//~^ ERROR expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + +const C: [u32; 0.0] = []; +//~^ ERROR expected `usize` for array length, found float [E0306] +//~| NOTE expected `usize` fn main() { } diff --git a/src/test/compile-fail/bad-bang-ann-3.rs b/src/test/compile-fail/bad-bang-ann-3.rs index de315a41361..1a5496f0551 100644 --- a/src/test/compile-fail/bad-bang-ann-3.rs +++ b/src/test/compile-fail/bad-bang-ann-3.rs @@ -11,7 +11,9 @@ // Tests that a function with a ! annotation always actually fails fn bad_bang(i: usize) -> ! { - return 7; //~ ERROR `return` in a function declared as diverging [E0166] + return 7; + //~^ ERROR `return` in a function declared as diverging [E0166] + //~| NOTE diverging function cannot return } fn main() { bad_bang(5); } diff --git a/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs index 87e40df7663..ec330247f23 100644 --- a/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs +++ b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs @@ -22,4 +22,6 @@ fn main() { let mut books = vec![1,2,3]; spawn(|| books.push(4)); //~^ ERROR E0373 + //~| NOTE `books` is borrowed here + //~| NOTE may outlive borrowed value `books` } diff --git a/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs index 67700be890b..81685c32f2f 100644 --- a/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs +++ b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs @@ -20,6 +20,8 @@ fn foo<'a>(x: &'a i32) -> Box<FnMut()+'a> { let mut books = vec![1,2,3]; Box::new(|| books.push(4)) //~^ ERROR E0373 + //~| NOTE `books` is borrowed here + //~| NOTE may outlive borrowed value `books` } fn main() { } diff --git a/src/test/compile-fail/const-fn-mismatch.rs b/src/test/compile-fail/const-fn-mismatch.rs index d813cf32954..92568b27f7c 100644 --- a/src/test/compile-fail/const-fn-mismatch.rs +++ b/src/test/compile-fail/const-fn-mismatch.rs @@ -20,7 +20,9 @@ trait Foo { } impl Foo for u32 { - const fn f() -> u32 { 22 } //~ ERROR E0379 + const fn f() -> u32 { 22 } + //~^ ERROR E0379 + //~| NOTE trait fns cannot be const } fn main() { } diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs index 5dadd892f83..398dc2f2215 100644 --- a/src/test/compile-fail/const-integer-bool-ops.rs +++ b/src/test/compile-fail/const-integer-bool-ops.rs @@ -25,17 +25,35 @@ const X3: usize = -42 && -39; //~ ERROR E0080 const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here const Y: usize = 42.0 == 42.0; -const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length +const ARRR: [i32; Y] = [99; 1]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + const Y1: usize = 42.0 >= 42.0; -const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length +const ARRR1: [i32; Y] = [99; 1]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + const Y2: usize = 42.0 <= 42.0; -const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length +const ARRR2: [i32; Y] = [99; 1]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + const Y3: usize = 42.0 > 42.0; -const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length +const ARRR3: [i32; Y] = [99; 0]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + const Y4: usize = 42.0 < 42.0; -const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length +const ARRR4: [i32; Y] = [99; 0]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + const Y5: usize = 42.0 != 42.0; -const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length +const ARRR5: [i32; Y] = [99; 0]; +//~^ ERROR: expected `usize` for array length, found boolean [E0306] +//~| NOTE expected `usize` + fn main() { let _ = ARR; diff --git a/src/test/compile-fail/const-pattern-irrefutable.rs b/src/test/compile-fail/const-pattern-irrefutable.rs index 75b6397f4eb..11003067070 100644 --- a/src/test/compile-fail/const-pattern-irrefutable.rs +++ b/src/test/compile-fail/const-pattern-irrefutable.rs @@ -25,4 +25,5 @@ fn main() { //~^ NOTE cannot be named the same as a constant let d = 4; //~ ERROR let bindings cannot shadow constants //~^ NOTE cannot be named the same as a constant + fn f() {} // Check that the `NOTE`s still work with an item here (c.f. issue #35115). } diff --git a/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs b/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs index 23401db21d8..d48433ee928 100644 --- a/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs +++ b/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs @@ -19,6 +19,7 @@ trait Fun { struct Holder { x: String } impl<'a> Fun for Holder { //~ ERROR E0207 + //~| NOTE unconstrained lifetime parameter type Output = &'a str; fn call<'b>(&'b self) -> &'b str { &self.x[..] diff --git a/src/test/compile-fail/impl-wrong-item-for-trait.rs b/src/test/compile-fail/impl-wrong-item-for-trait.rs index 9b3e28cbc01..6452e50d089 100644 --- a/src/test/compile-fail/impl-wrong-item-for-trait.rs +++ b/src/test/compile-fail/impl-wrong-item-for-trait.rs @@ -12,7 +12,9 @@ trait Foo { fn bar(&self); - const MY_CONST: u32; + //~^ NOTE original trait requirement + //~| NOTE original trait requirement + const MY_CONST: u32; //~ NOTE original trait requirement } pub struct FooConstForMethod; @@ -21,6 +23,7 @@ impl Foo for FooConstForMethod { //~^ ERROR E0046 const bar: u64 = 1; //~^ ERROR E0323 + //~| NOTE does not match trait const MY_CONST: u32 = 1; } @@ -31,6 +34,7 @@ impl Foo for FooMethodForConst { fn bar(&self) {} fn MY_CONST() {} //~^ ERROR E0324 + //~| NOTE does not match trait } pub struct FooTypeForMethod; @@ -39,6 +43,7 @@ impl Foo for FooTypeForMethod { //~^ ERROR E0046 type bar = u64; //~^ ERROR E0325 + //~| NOTE does not match trait const MY_CONST: u32 = 1; } diff --git a/src/test/compile-fail/issue-15524.rs b/src/test/compile-fail/issue-15524.rs index bdf344dcdfe..3d6f224c249 100644 --- a/src/test/compile-fail/issue-15524.rs +++ b/src/test/compile-fail/issue-15524.rs @@ -12,13 +12,18 @@ const N: isize = 1; enum Foo { A = 1, - B = 1, //~ ERROR discriminant value `1isize` already exists - //~^^ NOTE conflicting + //~^ NOTE first use + //~| NOTE first use + //~| NOTE first use + B = 1, //~ ERROR discriminant value + //~^ NOTE enum already C = 0, - D, //~ ERROR discriminant value `1isize` already exists - //~^^^^^ NOTE conflicting - E = N, //~ ERROR discriminant value `1isize` already exists - //~^^^^^^^ NOTE conflicting + D, //~ ERROR discriminant value + //~^ NOTE enum already + + E = N, //~ ERROR discriminant value + //~^ NOTE enum already + } fn main() {} diff --git a/src/test/compile-fail/issue-18819.rs b/src/test/compile-fail/issue-18819.rs index 3591b982414..cf650460c3d 100644 --- a/src/test/compile-fail/issue-18819.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -23,6 +23,8 @@ fn print_x(_: &Foo<Item=bool>, extra: &str) { } fn main() { - print_x(X); //~error this function takes 2 parameters but 1 parameter was supplied - //~^ NOTE the following parameter types were expected: &Foo<Item=bool>, &str + print_x(X); + //~^ ERROR this function takes 2 parameters but 1 parameter was supplied + //~| NOTE the following parameter types were expected: &Foo<Item=bool>, &str + //~| NOTE expected 2 parameters } diff --git a/src/test/compile-fail/issue-22886.rs b/src/test/compile-fail/issue-22886.rs index 4aa2571cad0..d258a4a8b33 100644 --- a/src/test/compile-fail/issue-22886.rs +++ b/src/test/compile-fail/issue-22886.rs @@ -21,6 +21,7 @@ fn crash_please() { struct Newtype(Option<Box<usize>>); impl<'a> Iterator for Newtype { //~ ERROR E0207 + //~| NOTE unconstrained lifetime parameter type Item = &'a Box<usize>; fn next(&mut self) -> Option<&Box<usize>> { diff --git a/src/test/compile-fail/issue-23543.rs b/src/test/compile-fail/issue-23543.rs index 4ed44154c47..f1c559b6b88 100644 --- a/src/test/compile-fail/issue-23543.rs +++ b/src/test/compile-fail/issue-23543.rs @@ -16,6 +16,7 @@ pub trait D { fn f<T>(self) where T<Bogus = Foo>: A; //~^ ERROR associated type bindings are not allowed here [E0229] + //~| NOTE associate type not allowed here } fn main() {} diff --git a/src/test/compile-fail/issue-23544.rs b/src/test/compile-fail/issue-23544.rs index 1d7c2187045..3959c22d1d4 100644 --- a/src/test/compile-fail/issue-23544.rs +++ b/src/test/compile-fail/issue-23544.rs @@ -14,6 +14,7 @@ pub trait D { fn f<T>(self) where T<Bogus = Self::AlsoBogus>: A; //~^ ERROR associated type bindings are not allowed here [E0229] + //~| NOTE associate type not allowed here } fn main() {} diff --git a/src/test/compile-fail/issue-27008.rs b/src/test/compile-fail/issue-27008.rs index ee6ec527612..e89bff025e0 100644 --- a/src/test/compile-fail/issue-27008.rs +++ b/src/test/compile-fail/issue-27008.rs @@ -16,5 +16,6 @@ fn main() { //~| expected type `usize` //~| found type `S` //~| expected usize, found struct `S` - //~| ERROR expected usize for repeat count, found struct + //~| ERROR expected `usize` for repeat count, found struct [E0306] + //~| expected `usize` } diff --git a/src/test/compile-fail/issue-28568.rs b/src/test/compile-fail/issue-28568.rs index 7c051784f61..f03daafc637 100644 --- a/src/test/compile-fail/issue-28568.rs +++ b/src/test/compile-fail/issue-28568.rs @@ -11,12 +11,13 @@ struct MyStruct; impl Drop for MyStruct { -//~^ NOTE conflicting implementation is here +//~^ NOTE first implementation here fn drop(&mut self) { } } impl Drop for MyStruct { //~^ ERROR conflicting implementations of trait +//~| NOTE conflicting implementation for `MyStruct` fn drop(&mut self) { } } diff --git a/src/test/compile-fail/issue-3044.rs b/src/test/compile-fail/issue-3044.rs index 68046056fb3..d19e3b2c7b0 100644 --- a/src/test/compile-fail/issue-3044.rs +++ b/src/test/compile-fail/issue-3044.rs @@ -14,7 +14,7 @@ fn main() { needlesArr.iter().fold(|x, y| { }); //~^^ ERROR this function takes 2 parameters but 1 parameter was supplied - //~^^^ NOTE the following parameter types were expected - // + //~| NOTE the following parameter types were expected + //~| NOTE expected 2 parameters // the first error is, um, non-ideal. } diff --git a/src/test/compile-fail/issue-31221.rs b/src/test/compile-fail/issue-31221.rs index 2b3df9ad1d8..4997a6fee19 100644 --- a/src/test/compile-fail/issue-31221.rs +++ b/src/test/compile-fail/issue-31221.rs @@ -22,6 +22,7 @@ fn main() { //~^ NOTE this pattern matches any value Var2 => (), //~^ ERROR unreachable pattern + //~^^ NOTE this is an unreachable pattern }; match &s { &Var1 => (), @@ -29,6 +30,7 @@ fn main() { //~^ NOTE this pattern matches any value &Var2 => (), //~^ ERROR unreachable pattern + //~^^ NOTE this is an unreachable pattern }; let t = (Var1, Var1); match t { @@ -37,6 +39,7 @@ fn main() { //~^ NOTE this pattern matches any value anything => () //~^ ERROR unreachable pattern + //~^^ NOTE this is an unreachable pattern }; // `_` need not emit a note, it is pretty obvious already. let t = (Var1, Var1); @@ -45,5 +48,6 @@ fn main() { _ => (), anything => () //~^ ERROR unreachable pattern + //~^^ NOTE this is an unreachable pattern }; } diff --git a/src/test/compile-fail/issue-35139.rs b/src/test/compile-fail/issue-35139.rs index 67f0e7aaf97..5c4f161a500 100644 --- a/src/test/compile-fail/issue-35139.rs +++ b/src/test/compile-fail/issue-35139.rs @@ -17,6 +17,7 @@ pub trait MethodType { pub struct MTFn; impl<'a> MethodType for MTFn { //~ ERROR E0207 + //~| NOTE unconstrained lifetime parameter type GetProp = fmt::Debug + 'a; } diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs index cbc09a028c2..93556577ad3 100644 --- a/src/test/compile-fail/issue-3907.rs +++ b/src/test/compile-fail/issue-3907.rs @@ -18,6 +18,7 @@ struct S { } impl Foo for S { //~ ERROR: `Foo` is not a trait + //~| NOTE: not a trait //~| NOTE: type aliases cannot be used for traits fn bar() { } } diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index 9a1b5d9b83d..09371fbafcb 100644 --- a/src/test/compile-fail/issue-4335.rs +++ b/src/test/compile-fail/issue-4335.rs @@ -14,7 +14,10 @@ fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. id(Box::new(|| *v)) //~^ ERROR E0373 - //~| ERROR cannot move out of borrowed content + //~| NOTE `v` is borrowed here + //~| NOTE may outlive borrowed value `v` + //~| ERROR E0507 + //~| NOTE cannot move out of borrowed content } fn main() { diff --git a/src/test/compile-fail/issue-4935.rs b/src/test/compile-fail/issue-4935.rs index 438d238b6fe..58a84f3490b 100644 --- a/src/test/compile-fail/issue-4935.rs +++ b/src/test/compile-fail/issue-4935.rs @@ -11,5 +11,7 @@ // Regression test for issue #4935 fn foo(a: usize) {} -fn main() { foo(5, 6) } //~ ERROR this function takes 1 parameter but 2 parameters were supplied -//~^ NOTE the following parameter type was expected +fn main() { foo(5, 6) } +//~^ ERROR this function takes 1 parameter but 2 parameters were supplied +//~| NOTE the following parameter type was expected +//~| NOTE expected 1 parameter diff --git a/src/test/compile-fail/issue-5035.rs b/src/test/compile-fail/issue-5035.rs index 9648d64d1fb..c2154e8a6c0 100644 --- a/src/test/compile-fail/issue-5035.rs +++ b/src/test/compile-fail/issue-5035.rs @@ -11,6 +11,7 @@ trait I {} type K = I; impl K for isize {} //~ ERROR: `K` is not a trait + //~| NOTE: not a trait //~| NOTE: aliases cannot be used for traits use ImportError; //~ ERROR unresolved diff --git a/src/test/compile-fail/issue-5239-1.rs b/src/test/compile-fail/issue-5239-1.rs index 1ebef06008f..06e3c9a207b 100644 --- a/src/test/compile-fail/issue-5239-1.rs +++ b/src/test/compile-fail/issue-5239-1.rs @@ -13,4 +13,5 @@ fn main() { let x = |ref x: isize| -> isize { x += 1; }; //~^ ERROR E0368 + //~| NOTE cannot use `+=` on type `&isize` } diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs index 40322f5a5b5..239f380e6c4 100644 --- a/src/test/compile-fail/lint-unused-imports.rs +++ b/src/test/compile-fail/lint-unused-imports.rs @@ -79,6 +79,13 @@ fn g() { } } +// c.f. issue #35135 +#[allow(unused_variables)] +fn h() { + use test2::foo; //~ ERROR unused import + let foo = 0; +} + fn main() { cal(foo::Point{x:3, y:9}); let mut a = 3; diff --git a/src/test/compile-fail/method-call-err-msg.rs b/src/test/compile-fail/method-call-err-msg.rs index 212c09364cf..bcf676dbede 100644 --- a/src/test/compile-fail/method-call-err-msg.rs +++ b/src/test/compile-fail/method-call-err-msg.rs @@ -20,10 +20,13 @@ impl Foo { fn main() { let x = Foo; x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied + //~^ NOTE expected 0 parameters .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied //~^ NOTE the following parameter type was expected + //~| NOTE expected 1 parameter .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied //~^ NOTE the following parameter types were expected + //~| NOTE expected 2 parameters let y = Foo; y.zero() diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index 0b12a9acbcb..eba61ede8cb 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -19,6 +19,7 @@ struct Foo { fn struct_with_a_nested_enum_and_vector() { match (Foo { first: true, second: None }) { //~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered +//~| NOTE pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered Foo { first: true, second: None } => (), Foo { first: true, second: Some(_) } => (), Foo { first: false, second: None } => (), @@ -35,6 +36,7 @@ enum Color { fn enum_with_single_missing_variant() { match Color::Red { //~^ ERROR non-exhaustive patterns: `Red` not covered + //~| NOTE pattern `Red` not covered Color::CustomRGBA { .. } => (), Color::Green => () } @@ -47,6 +49,7 @@ enum Direction { fn enum_with_multiple_missing_variants() { match Direction::North { //~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered + //~| NOTE patterns `East`, `South` and `West` not covered Direction::North => () } } @@ -58,6 +61,7 @@ enum ExcessiveEnum { fn enum_with_excessive_missing_variants() { match ExcessiveEnum::First { //~^ ERROR `Second`, `Third`, `Fourth` and 8 more not covered + //~| NOTE patterns `Second`, `Third`, `Fourth` and 8 more not covered ExcessiveEnum::First => () } @@ -66,6 +70,7 @@ fn enum_with_excessive_missing_variants() { fn enum_struct_variant() { match Color::Red { //~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered + //~| NOTE pattern `CustomRGBA { a: true, .. }` not covered Color::Red => (), Color::Green => (), Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (), @@ -82,6 +87,7 @@ fn vectors_with_nested_enums() { let x: &'static [Enum] = &[Enum::First, Enum::Second(false)]; match *x { //~^ ERROR non-exhaustive patterns: `[Second(true), Second(false)]` not covered + //~| NOTE pattern `[Second(true), Second(false)]` not covered [] => (), [_] => (), [Enum::First, _] => (), @@ -95,6 +101,7 @@ fn vectors_with_nested_enums() { fn missing_nil() { match ((), false) { //~^ ERROR non-exhaustive patterns: `((), false)` not covered + //~| NOTE pattern `((), false)` not covered ((), true) => () } } diff --git a/src/test/compile-fail/not-enough-arguments.rs b/src/test/compile-fail/not-enough-arguments.rs index 1f5a54477dd..f2f61fcaeec 100644 --- a/src/test/compile-fail/not-enough-arguments.rs +++ b/src/test/compile-fail/not-enough-arguments.rs @@ -19,5 +19,6 @@ fn foo(a: isize, b: isize, c: isize, d:isize) { fn main() { foo(1, 2, 3); //~^ ERROR this function takes 4 parameters but 3 - //~^^ NOTE the following parameter types were expected + //~| NOTE the following parameter types were expected + //~| NOTE expected 4 parameters } diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs index 8763fb0913a..5865d93e128 100644 --- a/src/test/compile-fail/overloaded-calls-bad.rs +++ b/src/test/compile-fail/overloaded-calls-bad.rs @@ -42,7 +42,9 @@ fn main() { let ans = s(); //~^ ERROR this function takes 1 parameter but 0 parameters were supplied //~| NOTE the following parameter type was expected + //~| NOTE expected 1 parameter let ans = s("burma", "shave"); //~^ ERROR this function takes 1 parameter but 2 parameters were supplied //~| NOTE the following parameter type was expected + //~| NOTE expected 1 parameter } diff --git a/src/test/compile-fail/region-borrow-params-issue-29793-small.rs b/src/test/compile-fail/region-borrow-params-issue-29793-small.rs index 4fda8ec3f38..6be2adbe2a0 100644 --- a/src/test/compile-fail/region-borrow-params-issue-29793-small.rs +++ b/src/test/compile-fail/region-borrow-params-issue-29793-small.rs @@ -16,6 +16,10 @@ fn escaping_borrow_of_closure_params_1() { let g = |x: usize, y:usize| { + //~^ NOTE reference must be valid for the scope of call-site for function + //~| NOTE ...but borrowed value is only valid for the scope of function body + //~| NOTE reference must be valid for the scope of call-site for function + //~| NOTE ...but borrowed value is only valid for the scope of function body let f = |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 @@ -31,6 +35,10 @@ fn escaping_borrow_of_closure_params_1() { fn escaping_borrow_of_closure_params_2() { let g = |x: usize, y:usize| { + //~^ NOTE reference must be valid for the scope of call-site for function + //~| NOTE ...but borrowed value is only valid for the scope of function body + //~| NOTE reference must be valid for the scope of call-site for function + //~| NOTE ...but borrowed value is only valid for the scope of function body let f = |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 @@ -64,7 +72,11 @@ fn escaping_borrow_of_fn_params_1() { fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` return Box::new(f); }; @@ -75,7 +87,11 @@ fn escaping_borrow_of_fn_params_2() { fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` Box::new(f) }; @@ -99,7 +115,11 @@ fn escaping_borrow_of_method_params_1() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` return Box::new(f); } } @@ -113,7 +133,11 @@ fn escaping_borrow_of_method_params_2() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` Box::new(f) } } @@ -141,7 +165,11 @@ fn escaping_borrow_of_trait_impl_params_1() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` return Box::new(f); } } @@ -156,7 +184,11 @@ fn escaping_borrow_of_trait_impl_params_2() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` Box::new(f) } } @@ -184,7 +216,11 @@ fn escaping_borrow_of_trait_default_params_1() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` return Box::new(f); } } @@ -198,7 +234,11 @@ fn escaping_borrow_of_trait_default_params_2() { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> { let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) //~^ ERROR E0373 + //~| NOTE `x` is borrowed here + //~| NOTE may outlive borrowed value `x` //~| ERROR E0373 + //~| NOTE `y` is borrowed here + //~| NOTE may outlive borrowed value `y` Box::new(f) } } diff --git a/src/test/compile-fail/regions-nested-fns-2.rs b/src/test/compile-fail/regions-nested-fns-2.rs index 948dc8cd219..40ba34b26ed 100644 --- a/src/test/compile-fail/regions-nested-fns-2.rs +++ b/src/test/compile-fail/regions-nested-fns-2.rs @@ -13,8 +13,11 @@ fn ignore<F>(_f: F) where F: for<'z> FnOnce(&'z isize) -> &'z isize {} fn nested() { let y = 3; ignore( - |z| { //~ ERROR E0373 + |z| { + //~^ ERROR E0373 + //~| NOTE may outlive borrowed value `y` if false { &y } else { z } + //~^ NOTE `y` is borrowed here }); } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 1758b28a324..555dd0f0c39 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -20,23 +20,27 @@ fn main() { //~| expected type `usize` //~| found type `()` //~| expected usize, found () - //~| ERROR expected usize for repeat count, found tuple [E0306] + //~| ERROR expected `usize` for repeat count, found tuple [E0306] + //~| expected `usize` let c = [0; true]; //~^ ERROR mismatched types //~| expected usize, found bool - //~| ERROR expected usize for repeat count, found boolean [E0306] + //~| ERROR expected `usize` for repeat count, found boolean [E0306] + //~| expected `usize` let d = [0; 0.5]; //~^ ERROR mismatched types //~| expected type `usize` //~| found type `{float}` //~| expected usize, found floating-point variable - //~| ERROR expected usize for repeat count, found float [E0306] + //~| ERROR expected `usize` for repeat count, found float [E0306] + //~| expected `usize` let e = [0; "foo"]; //~^ ERROR mismatched types //~| expected type `usize` //~| found type `&'static str` //~| expected usize, found &-ptr - //~| ERROR expected usize for repeat count, found string literal [E0306] + //~| ERROR expected `usize` for repeat count, found string literal [E0306] + //~| expected `usize` let f = [0; -4_isize]; //~^ ERROR constant evaluation error //~| expected usize, found isize @@ -55,5 +59,6 @@ fn main() { //~| expected type `usize` //~| found type `main::G` //~| expected usize, found struct `main::G` - //~| ERROR expected usize for repeat count, found struct [E0306] + //~| ERROR expected `usize` for repeat count, found struct [E0306] + //~| expected `usize` } diff --git a/src/test/compile-fail/struct-fields-decl-dupe.rs b/src/test/compile-fail/struct-fields-decl-dupe.rs index 049569e8a18..dd9d7d29468 100644 --- a/src/test/compile-fail/struct-fields-decl-dupe.rs +++ b/src/test/compile-fail/struct-fields-decl-dupe.rs @@ -9,8 +9,10 @@ // except according to those terms. struct BuildData { + foo: isize, //~ NOTE `foo` first declared here foo: isize, - foo: isize, //~ ERROR field `foo` is already declared + //~^ ERROR field `foo` is already declared [E0124] + //~| NOTE field already declared } fn main() { diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index 13fdaa302f7..c78eebddbfd 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -13,4 +13,5 @@ trait TraitNotAStruct {} fn main() { TraitNotAStruct{ value: 0 }; //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071] + //~| NOTE not a struct } diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs index d8620ead836..cc9a7c84ede 100644 --- a/src/test/compile-fail/variadic-ffi-3.rs +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -18,8 +18,10 @@ fn main() { unsafe { foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied //~^ NOTE the following parameter types were expected + //~| NOTE expected at least 2 parameters foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied //~^ NOTE the following parameter types were expected + //~| NOTE expected at least 2 parameters let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~^ ERROR: mismatched types diff --git a/src/test/run-pass/auxiliary/typeid-intrinsic-aux1.rs b/src/test/run-pass/auxiliary/typeid-intrinsic-aux1.rs index 388d3238d42..42c0da6286b 100644 --- a/src/test/run-pass/auxiliary/typeid-intrinsic-aux1.rs +++ b/src/test/run-pass/auxiliary/typeid-intrinsic-aux1.rs @@ -21,14 +21,16 @@ pub struct E(Result<&'static str, isize>); pub type F = Option<isize>; pub type G = usize; pub type H = &'static str; +pub type I = Box<Fn()>; -pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() } -pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() } -pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() } -pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() } -pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() } -pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() } -pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() } -pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() } +pub fn id_A() -> TypeId { TypeId::of::<A>() } +pub fn id_B() -> TypeId { TypeId::of::<B>() } +pub fn id_C() -> TypeId { TypeId::of::<C>() } +pub fn id_D() -> TypeId { TypeId::of::<D>() } +pub fn id_E() -> TypeId { TypeId::of::<E>() } +pub fn id_F() -> TypeId { TypeId::of::<F>() } +pub fn id_G() -> TypeId { TypeId::of::<G>() } +pub fn id_H() -> TypeId { TypeId::of::<H>() } +pub fn id_I() -> TypeId { TypeId::of::<I>() } -pub unsafe fn foo<T: Any>() -> TypeId { TypeId::of::<T>() } +pub fn foo<T: Any>() -> TypeId { TypeId::of::<T>() } diff --git a/src/test/run-pass/auxiliary/typeid-intrinsic-aux2.rs b/src/test/run-pass/auxiliary/typeid-intrinsic-aux2.rs index 3ad307fd3b5..42c0da6286b 100644 --- a/src/test/run-pass/auxiliary/typeid-intrinsic-aux2.rs +++ b/src/test/run-pass/auxiliary/typeid-intrinsic-aux2.rs @@ -21,14 +21,16 @@ pub struct E(Result<&'static str, isize>); pub type F = Option<isize>; pub type G = usize; pub type H = &'static str; +pub type I = Box<Fn()>; -pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() } -pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() } -pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() } -pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() } -pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() } -pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() } -pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() } -pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() } +pub fn id_A() -> TypeId { TypeId::of::<A>() } +pub fn id_B() -> TypeId { TypeId::of::<B>() } +pub fn id_C() -> TypeId { TypeId::of::<C>() } +pub fn id_D() -> TypeId { TypeId::of::<D>() } +pub fn id_E() -> TypeId { TypeId::of::<E>() } +pub fn id_F() -> TypeId { TypeId::of::<F>() } +pub fn id_G() -> TypeId { TypeId::of::<G>() } +pub fn id_H() -> TypeId { TypeId::of::<H>() } +pub fn id_I() -> TypeId { TypeId::of::<I>() } -pub unsafe fn foo<T:Any>() -> TypeId { TypeId::of::<T>() } +pub fn foo<T: Any>() -> TypeId { TypeId::of::<T>() } diff --git a/src/test/run-pass/type-id-higher-rank-2.rs b/src/test/run-pass/type-id-higher-rank-2.rs new file mode 100644 index 00000000000..aead8bc264d --- /dev/null +++ b/src/test/run-pass/type-id-higher-rank-2.rs @@ -0,0 +1,40 @@ +// 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 that we can't ignore lifetimes by going through Any. + +use std::any::Any; + +struct Foo<'a>(&'a str); + +fn good(s: &String) -> Foo { Foo(s) } + +fn bad1(s: String) -> Option<&'static str> { + let a: Box<Any> = Box::new(good as fn(&String) -> Foo); + a.downcast_ref::<fn(&String) -> Foo<'static>>().map(|f| f(&s).0) +} + +trait AsStr<'a, 'b> { + fn get(&'a self) -> &'b str; +} + +impl<'a> AsStr<'a, 'a> for String { + fn get(&'a self) -> &'a str { self } +} + +fn bad2(s: String) -> Option<&'static str> { + let a: Box<Any> = Box::new(Box::new(s) as Box<for<'a> AsStr<'a, 'a>>); + a.downcast_ref::<Box<for<'a> AsStr<'a, 'static>>>().map(|x| x.get()) +} + +fn main() { + assert_eq!(bad1(String::from("foo")), None); + assert_eq!(bad2(String::from("bar")), None); +} diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs index c29fb5e86f5..827b05c0801 100644 --- a/src/test/run-pass/type-id-higher-rank.rs +++ b/src/test/run-pass/type-id-higher-rank.rs @@ -16,6 +16,9 @@ use std::any::{Any, TypeId}; +struct Struct<'a>(&'a ()); +trait Trait<'a> {} + fn main() { // Bare fns { @@ -34,6 +37,14 @@ fn main() { let e = TypeId::of::<for<'a> fn(fn(&'a isize) -> &'a isize)>(); let f = TypeId::of::<fn(for<'a> fn(&'a isize) -> &'a isize)>(); assert!(e != f); + + // Make sure lifetime parameters of items are not ignored. + let g = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'a>>(); + let h = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'static>>(); + let i = TypeId::of::<for<'a, 'b> fn(&'a Trait<'b>) -> Struct<'b>>(); + assert!(g != h); + assert!(g != i); + assert!(h != i); } // Boxed unboxed closures { diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index 4bd82baafeb..e99a5f69af4 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -23,36 +23,37 @@ struct A; struct Test; pub fn main() { - unsafe { - assert_eq!(TypeId::of::<other1::A>(), other1::id_A()); - assert_eq!(TypeId::of::<other1::B>(), other1::id_B()); - assert_eq!(TypeId::of::<other1::C>(), other1::id_C()); - assert_eq!(TypeId::of::<other1::D>(), other1::id_D()); - assert_eq!(TypeId::of::<other1::E>(), other1::id_E()); - assert_eq!(TypeId::of::<other1::F>(), other1::id_F()); - assert_eq!(TypeId::of::<other1::G>(), other1::id_G()); - assert_eq!(TypeId::of::<other1::H>(), other1::id_H()); + assert_eq!(TypeId::of::<other1::A>(), other1::id_A()); + assert_eq!(TypeId::of::<other1::B>(), other1::id_B()); + assert_eq!(TypeId::of::<other1::C>(), other1::id_C()); + assert_eq!(TypeId::of::<other1::D>(), other1::id_D()); + assert_eq!(TypeId::of::<other1::E>(), other1::id_E()); + assert_eq!(TypeId::of::<other1::F>(), other1::id_F()); + assert_eq!(TypeId::of::<other1::G>(), other1::id_G()); + assert_eq!(TypeId::of::<other1::H>(), other1::id_H()); + assert_eq!(TypeId::of::<other1::I>(), other1::id_I()); - assert_eq!(TypeId::of::<other2::A>(), other2::id_A()); - assert_eq!(TypeId::of::<other2::B>(), other2::id_B()); - assert_eq!(TypeId::of::<other2::C>(), other2::id_C()); - assert_eq!(TypeId::of::<other2::D>(), other2::id_D()); - assert_eq!(TypeId::of::<other2::E>(), other2::id_E()); - assert_eq!(TypeId::of::<other2::F>(), other2::id_F()); - assert_eq!(TypeId::of::<other2::G>(), other2::id_G()); - assert_eq!(TypeId::of::<other2::H>(), other2::id_H()); + assert_eq!(TypeId::of::<other2::A>(), other2::id_A()); + assert_eq!(TypeId::of::<other2::B>(), other2::id_B()); + assert_eq!(TypeId::of::<other2::C>(), other2::id_C()); + assert_eq!(TypeId::of::<other2::D>(), other2::id_D()); + assert_eq!(TypeId::of::<other2::E>(), other2::id_E()); + assert_eq!(TypeId::of::<other2::F>(), other2::id_F()); + assert_eq!(TypeId::of::<other2::G>(), other2::id_G()); + assert_eq!(TypeId::of::<other2::H>(), other2::id_H()); + assert_eq!(TypeId::of::<other1::I>(), other2::id_I()); - assert_eq!(other1::id_F(), other2::id_F()); - assert_eq!(other1::id_G(), other2::id_G()); - assert_eq!(other1::id_H(), other2::id_H()); + assert_eq!(other1::id_F(), other2::id_F()); + assert_eq!(other1::id_G(), other2::id_G()); + assert_eq!(other1::id_H(), other2::id_H()); + assert_eq!(other1::id_I(), other2::id_I()); - assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>()); - assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>()); - assert_eq!(other2::foo::<isize>(), other1::foo::<isize>()); - assert_eq!(TypeId::of::<A>(), other2::foo::<A>()); - assert_eq!(TypeId::of::<A>(), other1::foo::<A>()); - assert_eq!(other2::foo::<A>(), other1::foo::<A>()); - } + assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>()); + assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>()); + assert_eq!(other2::foo::<isize>(), other1::foo::<isize>()); + assert_eq!(TypeId::of::<A>(), other2::foo::<A>()); + assert_eq!(TypeId::of::<A>(), other1::foo::<A>()); + assert_eq!(other2::foo::<A>(), other1::foo::<A>()); // sanity test of TypeId let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(), diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr index cf3f187af93..69560174346 100644 --- a/src/test/ui/codemap_tests/two_files.stderr +++ b/src/test/ui/codemap_tests/two_files.stderr @@ -2,7 +2,7 @@ error[E0404]: `Bar` is not a trait --> $DIR/two_files.rs:16:6 | 16 | impl Bar for Baz { } - | ^^^ + | ^^^ not a trait | = note: type aliases cannot be used for traits diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 8b7164819a7..72df09b7669 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -24,7 +24,7 @@ struct Test { const TEST_REPOS: &'static [Test] = &[Test { name: "cargo", repo: "https://github.com/rust-lang/cargo", - sha: "7d79da08238e3d47e0bc4406155bdcc45ccb8c82", + sha: "fd90fd642d404d8c66505ca8db742c664ea352f2", lock: None, }, Test { |
