-.TH RUSTC "1" "August 2015" "rustc 1.2.0" "User Commands"
+.TH RUSTC "1" "August 2016" "rustc 1.12.0" "User Commands"
.SH NAME
rustc \- The Rust compiler
.SH SYNOPSIS
See https://github.com/rust\-lang/rust/issues for issues.
.SH "AUTHOR"
-See \fIAUTHORS.txt\fR in the Rust source distribution.
+See https://github.com/rust\-lang/rust/graphs/contributors or use `git log --all --format='%cN <%cE>' | sort -u` in the rust source distribution.
.SH "COPYRIGHT"
This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms.
-.TH RUSTDOC "1" "August 2015" "rustdoc 1.2.0" "User Commands"
+.TH RUSTDOC "1" "August 2016" "rustdoc 1.12.0" "User Commands"
.SH NAME
rustdoc \- generate documentation from Rust source code
.SH SYNOPSIS
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.
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
== != < > <= >=
&&
||
-= ..
+.. ...
+=
```
Operators at the same precedence level are evaluated left-to-right. [Unary
/// 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
}
/// 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
}
/// 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 {
/// 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
/// 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
/// ```
/// #![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
/// // 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
/// 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);
/// ```
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};
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
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() {
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,
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 => {
//! - 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;
//! 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;
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::*;
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;
/// 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.
}
}
+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>,
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), \
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) {
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();
},
}
}
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) => {
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);
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)
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);
}
_ => {}
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();
});
}
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));
}
}
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) => {
}
}
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 {
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();
});
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();
}
}
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");
}
}
_ => {}
// 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};
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;
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 {
}
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| {
}
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
Mode::Var
}
}
- _ => Mode::Var
+ _ => Mode::Var,
};
let qualif = self.with_mode(mode, |this| {
}
/// 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(),
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),
}
}
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);
}
// 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 {
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;
}
_ => {}
}
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.
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())
}
/// 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() => {
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);
}
}
}
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();
}
Categorization::Rvalue(..) |
Categorization::Upvar(..) |
- Categorization::Local(..) => break
+ Categorization::Local(..) => break,
}
}
}
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
euv::LoanCause::AutoUnsafe => {
return;
}
- _ => { }
+ _ => {}
}
let mut cur = &cmt;
// 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,
_ => {}
}
}
}
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) {}
}
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;
```
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
```
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
}
#![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;
#[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> {
}
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;
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);
}
}
}
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)]
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)
}
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};
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);
}
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);
}
}
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);
}
_ => {}
}
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,
}
}
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) {
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");
// 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;
}
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) {
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));
}
}
}
// 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();
}
}
}
- _ => ()
+ _ => (),
}
- },
- _ => ()
+ }
+ _ => (),
}
intravisit::walk_expr(self, e);
}
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};
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 }
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);
}
}
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());
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);
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.
}
use foo::MyTrait::do_something;
+// error: `do_something` is not directly importable
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.
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
/// 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
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,
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) => {
}
}
- 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.
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),
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)
}
}
- let mut search_module = module_;
let mut index = index;
let module_path_len = module_path.len();
}
/// 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, _) => {
if new_module.is_normal() {
return Some(new_module);
}
- module_ = new_module;
+ module = new_module;
}
}
}
/// 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,
}
}
"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() {
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)
})
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(..) => {
self,
ident.span,
ResolutionError::BindingShadowsSomethingUnacceptable(
- pat_src.descr(), resolution.kind_name(), ident.node.name)
+ pat_src.descr(), ident.node.name, binding.unwrap())
);
None
}
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);
}
}
};
use Module;
use Namespace::{self, TypeNS, ValueNS};
-use {NameBinding, NameBindingKind, PrivacyError};
+use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding};
use ResolveResult;
use ResolveResult::*;
use Resolver;
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};
}
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 }
}
}
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 {
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> {
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,
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() {
}
};
- 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
}
}
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
//
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 {
}
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);
/// 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 {
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,
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;
}
}
}
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),
};
// 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;
}
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();
}
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(());
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");
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() {
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);
}
}
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;
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);
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);
}
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)
}
}
"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,
}
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
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;
}
// 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()
}
}
}
// 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());
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) => {
&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(_) => {
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()
}
}
}
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);
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: {}",
remaining_fields.insert(field.name, field);
}
+ let mut seen_fields = FnvHashMap();
+
let mut error_happened = false;
// Typecheck each field.
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);
}
};
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;
}
// 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();
}
}
}
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());
// 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 `{}`",
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");
}
} else {
bug!("found external impl of Drop trait on \
- :omething other than a struct");
+ something other than a struct");
}
}
}
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 `{}`",
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) |
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);
}
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();
};
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();
+
}
```
"##,
+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.
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
}
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;
}
_ => ()
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 }
#[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);
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())
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() }
}
///
/// 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 {
///
/// 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)]
/// 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)
/// 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 {
///
/// 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 {
///
/// 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 {
///
/// 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 {
}
/// 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 {
///
/// 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 {
///
/// 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 }
}
///
/// [`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()) }
///
/// 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()) }
///
/// 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()) }
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 {
///
/// 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 }
#[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",
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)
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),
*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).
///
/// 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) {
///
/// 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();
fn main() {
let foo = Foo;
let ref_foo = &&Foo;
- ref_foo.foo(); //~ ERROR E0055
+ ref_foo.foo();
+ //~^ ERROR E0055
+ //~| NOTE deref recursion limit reached
}
}
fn main() {
- unsafe { printf(); } //~ ERROR E0060
+ unsafe { printf(); }
+ //~^ ERROR E0060
+ //~| NOTE expected at least 1 parameter
+ //~| NOTE the following parameter type was expected
}
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
}
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
};
}
// 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() {
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
}
enum Foo {
Q = "32" //~ ERROR E0079
+ //~^ expected 'isize' type
}
fn main() {
// 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() {
}
// except according to those terms.
struct Foo<'a>(&'a str);
+struct Buzz<'a, 'b>(&'a str, &'b str);
enum Bar {
A,
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() {
// except according to those terms.
type X = u32<i32>; //~ ERROR E0109
+ //~| NOTE type parameter not allowed
fn main() {
}
// except according to those terms.
type X = u32<'static>; //~ ERROR E0110
+ //~| NOTE lifetime parameter not allowed on this type
fn main() {
}
fn get(&self) -> usize;
}
-impl<T> MyTrait for T {
+impl<T> MyTrait for T { //~ NOTE first implementation here
fn get(&self) -> usize { 0 }
}
}
impl MyTrait for Foo { //~ ERROR E0119
+ //~| NOTE conflicting implementation for `Foo`
fn get(&self) -> usize { self.value }
}
trait MyTrait {}
-impl Drop for MyTrait { //~ ERROR E0120
+impl Drop for MyTrait {
+ //~^ ERROR E0120
+ //~| NOTE implementing Drop requires a struct
fn drop(&mut self) {}
}
// 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() {
#[start]
fn f<T>() {} //~ ERROR E0132
+ //~| NOTE start function cannot have type parameters
fn main() {
}
#![feature(main)]
#[main]
-fn foo() {}
+fn foo() {} //~ NOTE first #[main] function
#[main]
-fn f() {} //~ ERROR E0137
+fn f() {}
+//~^ ERROR E0137
+//~| NOTE additional #[main] function
// 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() {
}
// 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() {
}
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() {
struct Foo;
impl<T: Default> Foo { //~ ERROR E0207
+ //~| NOTE unconstrained lifetime parameter
fn get(&self) -> T {
<T as Default>::default()
}
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() {
}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod foo {
+ pub trait MyTrait {
+ fn do_something();
+ }
+}
+
+use foo::MyTrait::do_something; //~ ERROR E0253
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate collections;
+
+mod foo {
+ pub trait collections {
+ fn do_something();
+ }
+}
+
+use foo::collections; //~ ERROR E0254
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use bar::foo;
+
+fn foo() {} //~ ERROR E0255
+
+mod bar {
+ pub fn foo() {}
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate collections;
+extern crate libc as collections; //~ ERROR E0259
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate collections;
+
+mod collections { //~ ERROR E0260
+ pub trait MyTrait {
+ fn do_something();
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(x: &'a str) { } //~ ERROR E0261
+
+struct Foo {
+ x: &'a str, //~ ERROR E0261
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<'static>(x: &'static str) { } //~ ERROR E0262
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } //~ ERROR E0263
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(lang_items)]
+
+extern "C" {
+ #[lang = "cake"]
+ fn cake(); //~ ERROR E0264
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let w = || { break; }; //~ ERROR E0267
+}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ break; //~ ERROR E0268
+}
// 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() {
}
// 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); }
let mut books = vec![1,2,3];
spawn(|| books.push(4));
//~^ ERROR E0373
+ //~| NOTE `books` is borrowed here
+ //~| NOTE may outlive borrowed value `books`
}
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() { }
}
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() { }
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;
//~^ 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).
}
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[..]
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;
//~^ ERROR E0046
const bar: u64 = 1;
//~^ ERROR E0323
+ //~| NOTE does not match trait
const MY_CONST: u32 = 1;
}
fn bar(&self) {}
fn MY_CONST() {}
//~^ ERROR E0324
+ //~| NOTE does not match trait
}
pub struct FooTypeForMethod;
//~^ ERROR E0046
type bar = u64;
//~^ ERROR E0325
+ //~| NOTE does not match trait
const MY_CONST: u32 = 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() {}
}
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
}
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>> {
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() {}
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() {}
//~| 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`
}
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) { }
}
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.
}
//~^ NOTE this pattern matches any value
Var2 => (),
//~^ ERROR unreachable pattern
+ //~^^ NOTE this is an unreachable pattern
};
match &s {
&Var1 => (),
//~^ NOTE this pattern matches any value
&Var2 => (),
//~^ ERROR unreachable pattern
+ //~^^ NOTE this is an unreachable pattern
};
let t = (Var1, Var1);
match t {
//~^ 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);
_ => (),
anything => ()
//~^ ERROR unreachable pattern
+ //~^^ NOTE this is an unreachable pattern
};
}
pub struct MTFn;
impl<'a> MethodType for MTFn { //~ ERROR E0207
+ //~| NOTE unconstrained lifetime parameter
type GetProp = fmt::Debug + 'a;
}
}
impl Foo for S { //~ ERROR: `Foo` is not a trait
+ //~| NOTE: not a trait
//~| NOTE: type aliases cannot be used for traits
fn bar() { }
}
// 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() {
// 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
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
fn main() {
let x = |ref x: isize| -> isize { x += 1; };
//~^ ERROR E0368
+ //~| NOTE cannot use `+=` on type `&isize`
}
}
}
+// 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;
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()
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 } => (),
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 => ()
}
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 => ()
}
}
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 => ()
}
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 } => (),
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, _] => (),
fn missing_nil() {
match ((), false) {
//~^ ERROR non-exhaustive patterns: `((), false)` not covered
+ //~| NOTE pattern `((), false)` not covered
((), true) => ()
}
}
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
}
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
}
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
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
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);
};
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)
};
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);
}
}
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)
}
}
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);
}
}
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)
}
}
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);
}
}
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)
}
}
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
});
}
//~| 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
//~| 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`
}
// 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() {
fn main() {
TraitNotAStruct{ value: 0 };
//~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
+ //~| NOTE not a struct
}
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
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>() }
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>() }
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
use std::any::{Any, TypeId};
+struct Struct<'a>(&'a ());
+trait Trait<'a> {}
+
fn main() {
// Bare fns
{
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
{
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>(),
--> $DIR/two_files.rs:16:6
|
16 | impl Bar for Baz { }
- | ^^^
+ | ^^^ not a trait
|
= note: type aliases cannot be used for traits
const TEST_REPOS: &'static [Test] = &[Test {
name: "cargo",
repo: "https://github.com/rust-lang/cargo",
- sha: "7d79da08238e3d47e0bc4406155bdcc45ccb8c82",
+ sha: "fd90fd642d404d8c66505ca8db742c664ea352f2",
lock: None,
},
Test {