}
/// Checks if `Rc::try_unwrap` would return `Ok`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(rc_would_unwrap)]
+ ///
+ /// use std::rc::Rc;
+ ///
+ /// let x = Rc::new(3);
+ /// assert!(Rc::would_unwrap(&x));
+ /// assert_eq!(Rc::try_unwrap(x), Ok(3));
+ ///
+ /// let x = Rc::new(4);
+ /// let _y = x.clone();
+ /// assert!(!Rc::would_unwrap(&x));
+ /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
+ /// ```
#[unstable(feature = "rc_would_unwrap",
reason = "just added for niche usecase",
issue = "28356")]
/// [`OsString`]: ../../std/ffi/struct.OsString.html
///
/// Indexing is intended to be a constant-time operation, but UTF-8 encoding
-/// does not allow us to do this. Furtheremore, it's not clear what sort of
+/// does not allow us to do this. Furthermore, it's not clear what sort of
/// thing the index should return: a byte, a codepoint, or a grapheme cluster.
/// The [`as_bytes()`] and [`chars()`] methods return iterators over the first
/// two, respectively.
use cmp::PartialOrd;
use fmt;
use marker::{Sized, Unsize};
+use result::Result::{self, Ok, Err};
/// The `Drop` trait is used to run some code when a value goes out of scope.
/// This is sometimes called a 'destructor'.
///
/// # Examples
///
-/// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
-/// calling `mul`, and therefore, `main` prints `Multiplying!`.
+/// Implementing a `Mul`tipliable rational number struct:
///
/// ```
/// use std::ops::Mul;
///
-/// struct Foo;
+/// // The uniqueness of rational numbers in lowest terms is a consequence of
+/// // the fundamental theorem of arithmetic.
+/// #[derive(Eq)]
+/// #[derive(PartialEq, Debug)]
+/// struct Rational {
+/// nominator: usize,
+/// denominator: usize,
+/// }
///
-/// impl Mul for Foo {
-/// type Output = Foo;
+/// impl Rational {
+/// fn new(nominator: usize, denominator: usize) -> Self {
+/// if denominator == 0 {
+/// panic!("Zero is an invalid denominator!");
+/// }
///
-/// fn mul(self, _rhs: Foo) -> Foo {
-/// println!("Multiplying!");
-/// self
+/// // Reduce to lowest terms by dividing by the greatest common
+/// // divisor.
+/// let gcd = gcd(nominator, denominator);
+/// Rational {
+/// nominator: nominator / gcd,
+/// denominator: denominator / gcd,
+/// }
/// }
/// }
///
-/// fn main() {
-/// Foo * Foo;
+/// impl Mul for Rational {
+/// // The multiplication of rational numbers is a closed operation.
+/// type Output = Self;
+///
+/// fn mul(self, rhs: Self) -> Self {
+/// let nominator = self.nominator * rhs.nominator;
+/// let denominator = self.denominator * rhs.denominator;
+/// Rational::new(nominator, denominator)
+/// }
/// }
+///
+/// // Euclid's two-thousand-year-old algorithm for finding the greatest common
+/// // divisor.
+/// fn gcd(x: usize, y: usize) -> usize {
+/// let mut x = x;
+/// let mut y = y;
+/// while y != 0 {
+/// let t = y;
+/// y = x % y;
+/// x = t;
+/// }
+/// x
+/// }
+///
+/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
+/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4),
+/// Rational::new(1, 2));
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. Here is an
///
/// # Examples
///
-/// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
-/// calling `rem`, and therefore, `main` prints `Remainder-ing!`.
+/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is
+/// implemented, one can use the `%` operator to find out what the remaining
+/// elements of the slice would be after splitting it into equal slices of a
+/// given length.
///
/// ```
/// use std::ops::Rem;
///
-/// struct Foo;
+/// #[derive(PartialEq, Debug)]
+/// struct SplitSlice<'a, T: 'a> {
+/// slice: &'a [T],
+/// }
///
-/// impl Rem for Foo {
-/// type Output = Foo;
+/// impl<'a, T> Rem<usize> for SplitSlice<'a, T> {
+/// type Output = SplitSlice<'a, T>;
///
-/// fn rem(self, _rhs: Foo) -> Foo {
-/// println!("Remainder-ing!");
-/// self
+/// fn rem(self, modulus: usize) -> Self {
+/// let len = self.slice.len();
+/// let rem = len % modulus;
+/// let start = len - rem;
+/// SplitSlice {slice: &self.slice[start..]}
/// }
/// }
///
-/// fn main() {
-/// Foo % Foo;
-/// }
+/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3,
+/// // the remainder would be &[6, 7]
+/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3,
+/// SplitSlice { slice: &[6, 7] });
/// ```
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
///
/// # Examples
///
-/// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
-/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
+/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
+/// struct.
///
/// ```
/// use std::ops::BitAnd;
///
-/// struct Foo;
-///
-/// impl BitAnd for Foo {
-/// type Output = Foo;
-///
-/// fn bitand(self, _rhs: Foo) -> Foo {
-/// println!("Bitwise And-ing!");
-/// self
+/// #[derive(Debug)]
+/// struct BooleanVector {
+/// value: Vec<bool>,
+/// };
+///
+/// impl BitAnd for BooleanVector {
+/// type Output = Self;
+///
+/// fn bitand(self, rhs: Self) -> Self {
+/// BooleanVector {
+/// value: self.value
+/// .iter()
+/// .zip(rhs.value.iter())
+/// .map(|(x, y)| *x && *y)
+/// .collect(),
+/// }
/// }
/// }
///
-/// fn main() {
-/// Foo & Foo;
+/// impl PartialEq for BooleanVector {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.value == other.value
+/// }
/// }
+///
+/// let bv1 = BooleanVector { value: vec![true, true, false, false] };
+/// let bv2 = BooleanVector { value: vec![true, false, true, false] };
+/// let expected = BooleanVector { value: vec![true, false, false, false] };
+/// assert_eq!(bv1 & bv2, expected);
/// ```
#[lang = "bitand"]
#[stable(feature = "rust1", since = "1.0.0")]
///
/// # Examples
///
-/// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up
-/// calling `index`, and therefore, `main` prints `Indexing!`.
+/// This example implements `Index` on a read-only `NucleotideCount` container,
+/// enabling individual counts to be retrieved with index syntax.
///
/// ```
/// use std::ops::Index;
///
-/// #[derive(Copy, Clone)]
-/// struct Foo;
-/// struct Bar;
+/// enum Nucleotide {
+/// A,
+/// C,
+/// G,
+/// T,
+/// }
///
-/// impl Index<Bar> for Foo {
-/// type Output = Foo;
+/// struct NucleotideCount {
+/// a: usize,
+/// c: usize,
+/// g: usize,
+/// t: usize,
+/// }
///
-/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
-/// println!("Indexing!");
-/// self
+/// impl Index<Nucleotide> for NucleotideCount {
+/// type Output = usize;
+///
+/// fn index(&self, nucleotide: Nucleotide) -> &usize {
+/// match nucleotide {
+/// Nucleotide::A => &self.a,
+/// Nucleotide::C => &self.c,
+/// Nucleotide::G => &self.g,
+/// Nucleotide::T => &self.t,
+/// }
/// }
/// }
///
-/// fn main() {
-/// Foo[Bar];
-/// }
+/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12};
+/// assert_eq!(nucleotide_count[Nucleotide::A], 14);
+/// assert_eq!(nucleotide_count[Nucleotide::C], 9);
+/// assert_eq!(nucleotide_count[Nucleotide::G], 10);
+/// assert_eq!(nucleotide_count[Nucleotide::T], 12);
/// ```
#[lang = "index"]
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
/// Creates a globally fresh place.
fn make_place() -> Self;
}
+
+/// A trait for types which have success and error states and are meant to work
+/// with the question mark operator.
+/// When the `?` operator is used with a value, whether the value is in the
+/// success or error state is determined by calling `translate`.
+///
+/// This trait is **very** experimental, it will probably be iterated on heavily
+/// before it is stabilised. Implementors should expect change. Users of `?`
+/// should not rely on any implementations of `Carrier` other than `Result`,
+/// i.e., you should not expect `?` to continue to work with `Option`, etc.
+#[unstable(feature = "question_mark_carrier", issue = "31436")]
+pub trait Carrier {
+ /// The type of the value when computation succeeds.
+ type Success;
+ /// The type of the value when computation errors out.
+ type Error;
+
+ /// Create a `Carrier` from a success value.
+ fn from_success(Self::Success) -> Self;
+
+ /// Create a `Carrier` from an error value.
+ fn from_error(Self::Error) -> Self;
+
+ /// Translate this `Carrier` to another implementation of `Carrier` with the
+ /// same associated types.
+ fn translate<T>(self) -> T where T: Carrier<Success=Self::Success, Error=Self::Error>;
+}
+
+#[unstable(feature = "question_mark_carrier", issue = "31436")]
+impl<U, V> Carrier for Result<U, V> {
+ type Success = U;
+ type Error = V;
+
+ fn from_success(u: U) -> Result<U, V> {
+ Ok(u)
+ }
+
+ fn from_error(e: V) -> Result<U, V> {
+ Err(e)
+ }
+
+ fn translate<T>(self) -> T
+ where T: Carrier<Success=U, Error=V>
+ {
+ match self {
+ Ok(u) => T::from_success(u),
+ Err(e) => T::from_error(e),
+ }
+ }
+}
+
+struct _DummyErrorType;
+
+impl Carrier for _DummyErrorType {
+ type Success = ();
+ type Error = ();
+
+ fn from_success(_: ()) -> _DummyErrorType {
+ _DummyErrorType
+ }
+
+ fn from_error(_: ()) -> _DummyErrorType {
+ _DummyErrorType
+ }
+
+ fn translate<T>(self) -> T
+ where T: Carrier<Success=(), Error=()>
+ {
+ T::from_success(())
+ }
+}
/// let x = 12;
/// let y = &x as *const i32;
///
-/// unsafe { println!("{}", std::ptr::read(y)); }
+/// unsafe {
+/// assert_eq!(std::ptr::read(y), 12);
+/// }
/// ```
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
///
/// unsafe {
/// std::ptr::write(y, z);
-/// println!("{}", std::ptr::read(y));
+/// assert_eq!(std::ptr::read(y), 12);
/// }
/// ```
#[inline]
/// let x = 12;
/// let y = &x as *const i32;
///
-/// unsafe { println!("{}", std::ptr::read_volatile(y)); }
+/// unsafe {
+/// assert_eq!(std::ptr::read_volatile(y), 12);
+/// }
/// ```
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
///
/// unsafe {
/// std::ptr::write_volatile(y, z);
-/// println!("{}", std::ptr::read_volatile(y));
+/// assert_eq!(std::ptr::read_volatile(y), 12);
/// }
/// ```
#[inline]
let inplace_finalize = ["ops", "InPlace", "finalize"];
let make_call = |this: &mut LoweringContext, p, args| {
- let path = this.core_path(e.span, p);
+ let path = this.std_path(e.span, p);
let path = this.expr_path(path, ThinVec::new());
this.expr_call(e.span, path, args)
};
ast_expr: &Expr,
path: &[&str],
fields: &[(&str, &P<Expr>)]) -> P<hir::Expr> {
- let strs = this.std_path(&iter::once(&"ops")
- .chain(path)
- .map(|s| *s)
- .collect::<Vec<_>>());
-
- let structpath = this.path_global(ast_expr.span, strs);
+ let struct_path = this.std_path(ast_expr.span,
+ &iter::once(&"ops").chain(path)
+ .map(|s| *s)
+ .collect::<Vec<_>>());
let hir_expr = if fields.len() == 0 {
- this.expr_path(structpath, ast_expr.attrs.clone())
+ this.expr_path(struct_path, ast_expr.attrs.clone())
} else {
let fields = fields.into_iter().map(|&(s, e)| {
let expr = this.lower_expr(&e);
}).collect();
let attrs = ast_expr.attrs.clone();
- this.expr_struct(ast_expr.span, structpath, fields, None, attrs)
+ this.expr_struct(ast_expr.span, struct_path, fields, None, attrs)
};
this.signal_block_expr(hir_vec![],
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
- let next_path = {
- let strs = self.std_path(&["iter", "Iterator", "next"]);
-
- self.path_global(e.span, strs)
- };
+ let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
let iter = self.expr_ident(e.span, iter, iter_pat.id);
let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
let next_path = self.expr_path(next_path, ThinVec::new());
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
- let into_iter_path = {
- let strs = self.std_path(&["iter", "IntoIterator", "into_iter"]);
-
- self.path_global(e.span, strs)
- };
+ let into_iter_path = self.std_path(e.span,
+ &["iter", "IntoIterator", "into_iter"]);
let into_iter = self.expr_path(into_iter_path, ThinVec::new());
self.expr_call(e.span, into_iter, hir_vec![head])
// to:
//
// {
- // match <expr> {
+ // match { Carrier::translate( { <expr> } ) } {
// Ok(val) => val,
- // Err(err) => {
- // return Err(From::from(err))
- // }
+ // Err(err) => { return Carrier::from_error(From::from(err)); }
// }
// }
- // expand <expr>
- let sub_expr = self.lower_expr(sub_expr);
+ // { Carrier::translate( { <expr> } ) }
+ let discr = {
+ // expand <expr>
+ let sub_expr = self.lower_expr(sub_expr);
+ let sub_expr = self.signal_block_expr(hir_vec![],
+ sub_expr,
+ e.span,
+ hir::PopUnstableBlock,
+ ThinVec::new());
+
+ let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
+ let path = self.expr_path(path, ThinVec::new());
+ let call = self.expr_call(e.span, path, hir_vec![sub_expr]);
+
+ self.signal_block_expr(hir_vec![],
+ call,
+ e.span,
+ hir::PushUnstableBlock,
+ ThinVec::new())
+ };
// Ok(val) => val
let ok_arm = {
self.arm(hir_vec![ok_pat], val_expr)
};
- // Err(err) => return Err(From::from(err))
+ // Err(err) => { return Carrier::from_error(From::from(err)); }
let err_arm = {
let err_ident = self.str_to_ident("err");
let err_local = self.pat_ident(e.span, err_ident);
let from_expr = {
- let path = self.std_path(&["convert", "From", "from"]);
- let path = self.path_global(e.span, path);
+ let path = self.std_path(e.span, &["convert", "From", "from"]);
let from = self.expr_path(path, ThinVec::new());
let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
self.expr_call(e.span, from, hir_vec![err_expr])
};
- let err_expr = {
- let path = self.std_path(&["result", "Result", "Err"]);
- let path = self.path_global(e.span, path);
- let err_ctor = self.expr_path(path, ThinVec::new());
- self.expr_call(e.span, err_ctor, hir_vec![from_expr])
+ let from_err_expr = {
+ let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
+ let from_err = self.expr_path(path, ThinVec::new());
+ self.expr_call(e.span, from_err, hir_vec![from_expr])
};
- let err_pat = self.pat_err(e.span, err_local);
+
let ret_expr = self.expr(e.span,
- hir::Expr_::ExprRet(Some(err_expr)),
- ThinVec::new());
- self.arm(hir_vec![err_pat], ret_expr)
+ hir::Expr_::ExprRet(Some(from_err_expr)),
+ ThinVec::new());
+ let ret_stmt = self.stmt_expr(ret_expr);
+ let block = self.signal_block_stmt(ret_stmt, e.span,
+ hir::PushUnstableBlock, ThinVec::new());
+
+ let err_pat = self.pat_err(e.span, err_local);
+ self.arm(hir_vec![err_pat], block)
};
- return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm],
+ return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
hir::MatchSource::TryDesugar);
}
(respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
}
+ // Turns `<expr>` into `<expr>;`, note that this produces a StmtSemi, not a
+ // StmtExpr.
+ fn stmt_expr(&self, expr: P<hir::Expr>) -> hir::Stmt {
+ hir::Stmt {
+ span: expr.span,
+ node: hir::StmtSemi(expr, self.next_id()),
+ }
+ }
+
fn block_expr(&mut self, expr: P<hir::Expr>) -> P<hir::Block> {
self.block_all(expr.span, hir::HirVec::new(), Some(expr))
}
}
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
- let ok = self.std_path(&["result", "Result", "Ok"]);
- let path = self.path_global(span, ok);
+ let path = self.std_path(span, &["result", "Result", "Ok"]);
self.pat_enum(span, path, hir_vec![pat])
}
fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
- let err = self.std_path(&["result", "Result", "Err"]);
- let path = self.path_global(span, err);
+ let path = self.std_path(span, &["result", "Result", "Err"]);
self.pat_enum(span, path, hir_vec![pat])
}
fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
- let some = self.std_path(&["option", "Option", "Some"]);
- let path = self.path_global(span, some);
+ let path = self.std_path(span, &["option", "Option", "Some"]);
self.pat_enum(span, path, hir_vec![pat])
}
fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
- let none = self.std_path(&["option", "Option", "None"]);
- let path = self.path_global(span, none);
+ let path = self.std_path(span, &["option", "Option", "None"]);
self.pat_enum(span, path, hir_vec![])
}
}
}
- fn std_path(&mut self, components: &[&str]) -> Vec<Name> {
+ fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
let mut v = Vec::new();
if let Some(s) = self.crate_root {
v.push(token::intern(s));
// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
- fn core_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
- let idents = self.std_path(components);
+ fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
+ let idents = self.std_path_components(components);
self.path_global(span, idents)
}
});
self.expr_block(block, attrs)
}
+
+ fn signal_block_stmt(&mut self,
+ stmt: hir::Stmt,
+ span: Span,
+ rule: hir::BlockCheckMode,
+ attrs: ThinVec<Attribute>)
+ -> P<hir::Expr> {
+ let id = self.next_id();
+ let block = P(hir::Block {
+ rules: rule,
+ span: span,
+ id: id,
+ stmts: hir_vec![stmt],
+ expr: None,
+ });
+ self.expr_block(block, attrs)
+ }
}
let b_ty = &b_subst.types[i];
let variance = variances.map_or(ty::Invariant, |v| v.types[i]);
relation.relate_with_variance(variance, a_ty, b_ty)
- }).collect()?;
+ }).collect::<Result<_, _>>()?;
let regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| {
let b_r = &b_subst.regions[i];
let variance = variances.map_or(ty::Invariant, |v| v.regions[i]);
relation.relate_with_variance(variance, a_r, b_r)
- }).collect()?;
+ }).collect::<Result<_, _>>()?;
Ok(Substs::new(tcx, types, regions))
}
struct_span_err!(self.bccx, span, E0503,
"cannot use `{}` because it was mutably borrowed",
&self.bccx.loan_path_to_string(copy_path))
- .span_note(loan_span,
+ .span_label(loan_span,
&format!("borrow of `{}` occurs here",
&self.bccx.loan_path_to_string(&loan_path))
)
+ .span_label(span,
+ &format!("use of borrowed `{}`",
+ &self.bccx.loan_path_to_string(&loan_path)))
.emit();
}
}
}
mc::AliasableStatic |
mc::AliasableStaticMut => {
- struct_span_err!(
+ let mut err = struct_span_err!(
self.tcx.sess, span, E0388,
- "{} in a static location", prefix)
+ "{} in a static location", prefix);
+ err.span_label(span, &format!("cannot write data in a static definition"));
+ err
}
mc::AliasableBorrowed => {
struct_span_err!(
E0454: r##"
A link name was given with an empty name. Erroneous code example:
-```
+```compile_fail,E0454
#[link(name = "")] extern {} // error: #[link(name = "")] given with empty name
```
Erroneous code example:
-```compile_fail"
+```compile_fail,E0455
#[link(name = "FooCoreServices", kind = "framework")] extern {}
// OS used to compile is Linux for example
```
E0458: r##"
An unknown "kind" was specified for a link attribute. Erroneous code example:
-```
+```compile_fail,E0458
#[link(kind = "wonderful_unicorn")] extern {}
// error: unknown kind: `wonderful_unicorn`
```
E0459: r##"
A link was used without a name parameter. Erroneous code example:
-```
+```compile_fail,E0459
#[link(kind = "dylib")] extern {}
// error: #[link(...)] specified without `name = "foo"`
```
E0463: r##"
A plugin/crate was declared but cannot be found. Erroneous code example:
-```
+```compile_fail,E0463
#![feature(plugin)]
#![plugin(cookie_monster)] // error: can't find crate for `cookie_monster`
extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
pub fn build_reduced_graph(&mut self, krate: &Crate) {
let no_implicit_prelude = attr::contains_name(&krate.attrs, "no_implicit_prelude");
self.graph_root.no_implicit_prelude.set(no_implicit_prelude);
-
- let mut visitor = BuildReducedGraphVisitor {
- parent: self.graph_root,
- resolver: self,
- };
- visit::walk_crate(&mut visitor, krate);
+ visit::walk_crate(&mut BuildReducedGraphVisitor { resolver: self }, krate);
}
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
}
/// Constructs the reduced graph for one item.
- fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
- let parent = *parent_ref;
+ fn build_reduced_graph_for_item(&mut self, item: &Item) {
+ let parent = self.current_module;
+ let parent_vis = self.current_vis;
let name = item.ident.name;
let sp = item.span;
- self.current_module = parent;
let vis = self.resolve_visibility(&item.vis);
match item.node {
let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
let span = view_path.span;
- parent.add_import_directive(module_path, subclass, span, item.id, vis);
- self.unresolved_imports += 1;
+ self.add_import_directive(module_path, subclass, span, item.id, vis);
}
ViewPathList(_, ref source_items) => {
// Make sure there's at most one `mod` import in the list.
};
let subclass = ImportDirectiveSubclass::single(rename, name);
let (span, id) = (source_item.span, source_item.node.id());
- parent.add_import_directive(module_path, subclass, span, id, vis);
- self.unresolved_imports += 1;
+ self.add_import_directive(module_path, subclass, span, id, vis);
}
}
ViewPathGlob(_) => {
let subclass = GlobImport { is_prelude: is_prelude };
let span = view_path.span;
- parent.add_import_directive(module_path, subclass, span, item.id, vis);
- self.unresolved_imports += 1;
+ self.add_import_directive(module_path, subclass, span, item.id, vis);
}
}
}
});
self.define(parent, name, TypeNS, (module, sp, vis));
self.module_map.insert(item.id, module);
- *parent_ref = module;
+
+ // Descend into the module.
+ self.current_module = module;
+ self.current_vis = ty::Visibility::Restricted(item.id);
}
ItemKind::ForeignMod(..) => {}
}
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
}
+
+ visit::walk_item(&mut BuildReducedGraphVisitor { resolver: self }, item);
+ self.current_module = parent;
+ self.current_vis = parent_vis;
}
// Constructs the reduced graph for one variant. Variants exist in the
}
/// Constructs the reduced graph for one foreign item.
- fn build_reduced_graph_for_foreign_item(&mut self,
- foreign_item: &ForeignItem,
- parent: Module<'b>) {
+ fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem) {
+ let parent = self.current_module;
let name = foreign_item.ident.name;
let def = match foreign_item.node {
Def::Static(self.definitions.local_def_id(foreign_item.id), m)
}
};
- self.current_module = parent;
let vis = self.resolve_visibility(&foreign_item.vis);
self.define(parent, name, ValueNS, (def, foreign_item.span, vis));
}
- fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
+ fn build_reduced_graph_for_block(&mut self, block: &Block) {
+ let parent = self.current_module;
if self.block_needs_anonymous_module(block) {
let block_id = block.id;
let parent_link = BlockParentLink(parent, block_id);
let new_module = self.new_module(parent_link, None, false);
self.module_map.insert(block_id, new_module);
- *parent = new_module;
+ self.current_module = new_module; // Descend into the block.
}
+
+ visit::walk_block(&mut BuildReducedGraphVisitor { resolver: self }, block);
+ self.current_module = parent;
}
/// Builds the reduced graph for a single item in an external crate.
struct BuildReducedGraphVisitor<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
- parent: Module<'b>,
}
impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
fn visit_item(&mut self, item: &Item) {
- let old_parent = self.parent;
- self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
- visit::walk_item(self, item);
- self.parent = old_parent;
+ self.resolver.build_reduced_graph_for_item(item);
}
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
- self.resolver.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
+ self.resolver.build_reduced_graph_for_foreign_item(foreign_item);
}
fn visit_block(&mut self, block: &Block) {
- let old_parent = self.parent;
- self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
- visit::walk_block(self, block);
- self.parent = old_parent;
+ self.resolver.build_reduced_graph_for_block(block);
}
}
err
}
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0437,
"type `{}` is not a member of trait `{}`",
type_,
- trait_)
+ trait_);
+ err.span_label(span, &format!("not a member of trait `Foo`"));
+ err
}
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0438,
"const `{}` is not a member of trait `{}`",
const_,
- trait_)
+ trait_);
+ err.span_label(span, &format!("not a member of trait `Foo`"));
+ err
}
ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
struct_span_err!(resolver.session,
err
}
ResolutionError::StructVariantUsedAsFunction(path_name) => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0423,
"`{}` is the name of a struct or struct variant, but this expression \
uses it like a function name",
- path_name)
+ path_name);
+ err.span_label(span, &format!("struct called like a function"));
+ err
}
ResolutionError::SelfNotAvailableInStaticMethod => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0424,
- "`self` is not available in a static method. Maybe a `self` \
- argument is missing?")
+ "`self` is not available in a static method");
+ err.span_label(span, &format!("not available in static method"));
+ err.note(&format!("maybe a `self` argument is missing?"));
+ err
}
ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
is_field, def } => {
err
}
ResolutionError::UndeclaredLabel(name) => {
- struct_span_err!(resolver.session,
- span,
- E0426,
- "use of undeclared label `{}`",
- name)
+ let mut err = struct_span_err!(resolver.session,
+ span,
+ E0426,
+ "use of undeclared label `{}`",
+ name);
+ err.span_label(span, &format!("undeclared label `{}`",&name));
+ err
}
ResolutionError::SelfImportsOnlyAllowedWithin => {
struct_span_err!(resolver.session,
}
ResolutionError::UnresolvedImport(name) => {
let msg = match name {
- Some((n, p)) => format!("unresolved import `{}`{}", n, p),
+ Some((n, _)) => format!("unresolved import `{}`", n),
None => "unresolved import".to_owned(),
};
- struct_span_err!(resolver.session, span, E0432, "{}", msg)
+ let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg);
+ if let Some((_, p)) = name {
+ err.span_label(span, &p);
+ }
+ err
}
ResolutionError::FailedToResolve(msg) => {
let mut err = struct_span_err!(resolver.session, span, E0433,
closure form instead")
}
ResolutionError::AttemptToUseNonConstantValueInConstant => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0435,
- "attempt to use a non-constant value in a constant")
+ "attempt to use a non-constant value in a constant");
+ err.span_label(span, &format!("non-constant used with constant"));
+ err
}
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
let shadows_what = PathResolution::new(binding.def().unwrap()).kind_name();
extern_crate_id: Option<NodeId>,
resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
- unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>,
no_implicit_prelude: Cell<bool>,
- glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>,
+ glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>,
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
// Used to memoize the traits in this module for faster searches through all traits in scope.
// access the children must be preceded with a
// `populate_module_if_necessary` call.
populated: Cell<bool>,
-
- arenas: &'a ResolverArenas<'a>,
}
pub type Module<'a> = &'a ModuleS<'a>;
impl<'a> ModuleS<'a> {
- fn new(parent_link: ParentLink<'a>,
- def: Option<Def>,
- external: bool,
- arenas: &'a ResolverArenas<'a>) -> Self {
+ fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool) -> Self {
ModuleS {
parent_link: parent_link,
def: def,
extern_crate_id: None,
resolutions: RefCell::new(HashMap::new()),
- unresolved_imports: RefCell::new(Vec::new()),
no_implicit_prelude: Cell::new(false),
glob_importers: RefCell::new(Vec::new()),
globs: RefCell::new((Vec::new())),
traits: RefCell::new(None),
populated: Cell::new(!external),
- arenas: arenas
}
}
structs: FnvHashMap<DefId, Vec<Name>>,
- // The number of imports that are currently unresolved.
- unresolved_imports: usize,
+ // All imports known to succeed or fail.
+ determined_imports: Vec<&'a ImportDirective<'a>>,
+
+ // All non-determined imports.
+ indeterminate_imports: Vec<&'a ImportDirective<'a>>,
// The module that represents the current item scope.
current_module: Module<'a>,
+ // The visibility of `pub(self)` items in the current scope.
+ // Equivalently, the visibility required for an item to be accessible from the current scope.
+ current_vis: ty::Visibility,
+
// The current set of local scopes, for values.
// FIXME #4948: Reuse ribs to avoid allocation.
value_ribs: Vec<Rib<'a>>,
-> Resolver<'a> {
let root_def_id = DefId::local(CRATE_DEF_INDEX);
let graph_root =
- ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
+ ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false);
let graph_root = arenas.alloc_module(graph_root);
let mut module_map = NodeMap();
module_map.insert(CRATE_NODE_ID, graph_root);
trait_item_map: FnvHashMap(),
structs: FnvHashMap(),
- unresolved_imports: 0,
+ determined_imports: Vec::new(),
+ indeterminate_imports: Vec::new(),
current_module: graph_root,
+ current_vis: ty::Visibility::Restricted(ast::CRATE_NODE_ID),
value_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
type_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
label_ribs: Vec::new(),
/// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) {
self.current_module = self.graph_root;
+ self.current_vis = ty::Visibility::Restricted(ast::CRATE_NODE_ID);
visit::walk_crate(self, krate);
check_unused::check_crate(self, krate);
fn new_module(&self, parent_link: ParentLink<'a>, def: Option<Def>, external: bool)
-> Module<'a> {
- self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas))
+ self.arenas.alloc_module(ModuleS::new(parent_link, def, external))
}
fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def, local_node_id: NodeId)
-> Module<'a> {
- let mut module = ModuleS::new(parent_link, Some(def), false, self.arenas);
+ let mut module = ModuleS::new(parent_link, Some(def), false);
module.extern_crate_id = Some(local_node_id);
self.arenas.modules.alloc(module)
}
mut search_module: Module<'a>,
module_path: &[Name],
index: usize,
- span: Span)
+ span: Option<Span>)
-> ResolveResult<Module<'a>> {
- fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
- match module.resolve_name(needle, TypeNS, false) {
+ fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
+ -> Option<Module<'a>> {
+ match this.resolve_name_in_module(module, needle, TypeNS, false, None) {
Success(binding) if binding.is_extern_crate() => Some(module),
_ => match module.parent_link {
ModuleParentLink(ref parent, _) => {
- search_parent_externals(needle, parent)
+ search_parent_externals(this, needle, parent)
}
_ => None,
},
// modules as we go.
while index < module_path_len {
let name = module_path[index];
- match self.resolve_name_in_module(search_module, name, TypeNS, false, true) {
+ match self.resolve_name_in_module(search_module, name, TypeNS, false, span) {
Failed(None) => {
let segment_name = name.as_str();
let module_name = module_to_string(search_module);
let msg = if "???" == &module_name {
- match search_parent_externals(name, &self.current_module) {
+ let current_module = self.current_module;
+ match search_parent_externals(self, name, current_module) {
Some(module) => {
let path_str = names_to_string(module_path);
let target_mod_str = module_to_string(&module);
- let current_mod_str = module_to_string(&self.current_module);
+ let current_mod_str = module_to_string(current_module);
let prefix = if target_mod_str == current_mod_str {
"self::".to_string()
format!("Could not find `{}` in `{}`", segment_name, module_name)
};
- return Failed(Some((span, msg)));
+ return Failed(span.map(|span| (span, msg)));
}
Failed(err) => return Failed(err),
Indeterminate => {
// Check to see whether there are type bindings, and, if
// so, whether there is a module within.
if let Some(module_def) = binding.module() {
- self.check_privacy(name, binding, span);
search_module = module_def;
} else {
let msg = format!("Not a module `{}`", name);
- return Failed(Some((span, msg)));
+ return Failed(span.map(|span| (span, msg)));
}
}
}
fn resolve_module_path(&mut self,
module_path: &[Name],
use_lexical_scope: UseLexicalScopeFlag,
- span: Span)
+ span: Option<Span>)
-> ResolveResult<Module<'a>> {
if module_path.len() == 0 {
return Success(self.graph_root) // Use the crate root
// first component of the path in the current lexical
// scope and then proceed to resolve below that.
let ident = ast::Ident::with_empty_ctxt(module_path[0]);
- match self.resolve_ident_in_lexical_scope(ident, TypeNS, true)
+ match self.resolve_ident_in_lexical_scope(ident, TypeNS, span)
.and_then(LexicalScopeBinding::module) {
None => return Failed(None),
Some(containing_module) => {
}
}
- self.resolve_module_path_from_root(search_module,
- module_path,
- start_index,
- span)
+ self.resolve_module_path_from_root(search_module, module_path, start_index, span)
}
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
fn resolve_ident_in_lexical_scope(&mut self,
mut ident: ast::Ident,
ns: Namespace,
- record_used: bool)
+ record_used: Option<Span>)
-> Option<LexicalScopeBinding<'a>> {
if ns == TypeNS {
ident = ast::Ident::with_empty_ctxt(ident.name);
if module.def.is_some() {
return match self.prelude {
Some(prelude) if !module.no_implicit_prelude.get() => {
- prelude.resolve_name(name, ns, false).success()
- .map(LexicalScopeBinding::Item)
+ self.resolve_name_in_module(prelude, name, ns, false, None).success()
+ .map(LexicalScopeBinding::Item)
}
_ => None,
};
/// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
/// (b) some chain of `super::`.
/// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
- fn resolve_module_prefix(&mut self, module_path: &[Name], span: Span)
+ fn resolve_module_prefix(&mut self, module_path: &[Name], span: Option<Span>)
-> ResolveResult<ModulePrefixResult<'a>> {
// Start at the current module if we see `self` or `super`, or at the
// top of the crate otherwise.
match self.get_nearest_normal_module_parent(containing_module) {
None => {
let msg = "There are too many initial `super`s.".into();
- return Failed(Some((span, msg)));
+ return Failed(span.map(|span| (span, msg)));
}
Some(new_module) => {
containing_module = new_module;
return Success(PrefixFound(containing_module, i));
}
- /// Attempts to resolve the supplied name in the given module for the
- /// given namespace. If successful, returns the binding corresponding to
- /// the name.
- fn resolve_name_in_module(&mut self,
- module: Module<'a>,
- name: Name,
- namespace: Namespace,
- use_lexical_scope: bool,
- record_used: bool)
- -> ResolveResult<&'a NameBinding<'a>> {
- debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
-
- self.populate_module_if_necessary(module);
- module.resolve_name(name, namespace, use_lexical_scope).and_then(|binding| {
- if record_used {
- self.record_use(name, namespace, binding);
- }
- Success(binding)
- })
- }
-
// AST resolution
//
// We maintain a list of value ribs and type ribs.
let module = self.module_map.get(&id).cloned(); // clones a reference
if let Some(module) = module {
// Move down in the graph.
- let orig_module = ::std::mem::replace(&mut self.current_module, module);
+ let orig_module = replace(&mut self.current_module, module);
+ let orig_vis = replace(&mut self.current_vis, ty::Visibility::Restricted(id));
self.value_ribs.push(Rib::new(ModuleRibKind(module)));
self.type_ribs.push(Rib::new(ModuleRibKind(module)));
f(self);
self.current_module = orig_module;
+ self.current_vis = orig_vis;
self.value_ribs.pop();
self.type_ribs.pop();
} else {
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 binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, false)
+ let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None)
.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() ||
//
// Such behavior is required for backward compatibility.
// The same fallback is used when `a` resolves to nothing.
- let def = resolve_identifier_with_fallback(self, true).ok_or(false);
+ let def = resolve_identifier_with_fallback(self, Some(span)).ok_or(false);
return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res);
}
- let unqualified_def = resolve_identifier_with_fallback(self, false);
+ let unqualified_def = resolve_identifier_with_fallback(self, None);
let qualified_binding = self.resolve_module_relative_path(span, segments, namespace);
match (qualified_binding, unqualified_def) {
(Ok(binding), Some(ref ud)) if binding.def().unwrap() == ud.def => {
fn resolve_identifier(&mut self,
identifier: ast::Ident,
namespace: Namespace,
- record_used: bool)
+ record_used: Option<Span>)
-> Option<LocalDef> {
if identifier.name == keywords::Invalid.name() {
return None;
.collect::<Vec<_>>();
let containing_module;
- match self.resolve_module_path(&module_path, UseLexicalScope, span) {
+ match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
Failed(err) => {
let (span, msg) = match err {
Some((span, msg)) => (span, msg),
}
let name = segments.last().unwrap().identifier.name;
- let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
- result.success().map(|binding| {
- self.check_privacy(name, binding, span);
- binding
- }).ok_or(false)
+ let result =
+ self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+ result.success().ok_or(false)
}
/// Invariant: This must be called only during main resolution, not during
let root_module = self.graph_root;
let containing_module;
- match self.resolve_module_path_from_root(root_module,
- &module_path,
- 0,
- span) {
+ match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) {
Failed(err) => {
let (span, msg) = match err {
Some((span, msg)) => (span, msg),
}
let name = segments.last().unwrap().name();
- let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
- result.success().map(|binding| {
- self.check_privacy(name, binding, span);
- binding
- }).ok_or(false)
+ let result =
+ self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+ result.success().ok_or(false)
}
fn with_no_errors<T, F>(&mut self, f: F) -> T
fn with_empty_ribs<T, F>(&mut self, f: F) -> T
where F: FnOnce(&mut Resolver<'a>) -> T,
{
- use ::std::mem::replace;
let value_ribs = replace(&mut self.value_ribs, Vec::new());
let type_ribs = replace(&mut self.type_ribs, Vec::new());
let label_ribs = replace(&mut self.label_ribs, Vec::new());
match self.resolve_module_path(&name_path[..],
UseLexicalScope,
- expr.span) {
+ Some(expr.span)) {
Success(e) => {
if let Some(def_type) = e.def {
def = def_type;
ast::Visibility::Public => return ty::Visibility::Public,
ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
ast::Visibility::Restricted { ref path, id } => (path, id),
- ast::Visibility::Inherited => {
- let current_module =
- self.get_nearest_normal_module_parent_or_self(self.current_module);
- let id =
- self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
- return ty::Visibility::Restricted(id);
- }
+ ast::Visibility::Inherited => return self.current_vis,
};
let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier.name).collect();
let mut path_resolution = err_path_resolution();
- let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, path.span) {
+ let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, Some(path.span)) {
Success(module) => {
let def = module.def.unwrap();
path_resolution = PathResolution::new(def);
}
fn is_accessible(&self, vis: ty::Visibility) -> bool {
- let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
- let node_id = self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
- vis.is_accessible_from(node_id, self)
- }
-
- fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {
- if !self.is_accessible(binding.vis) {
- self.privacy_errors.push(PrivacyError(span, name, binding));
- }
+ vis.is_at_least(self.current_vis, self)
}
fn report_privacy_errors(&self) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use self::Determinacy::*;
use self::ImportDirectiveSubclass::*;
use Module;
}
}
+#[derive(Copy, Clone, Debug)]
+pub enum Determinacy {
+ Determined,
+ Undetermined,
+}
+
/// Contains data for specific types of import directives.
#[derive(Clone, Debug)]
-pub enum ImportDirectiveSubclass {
+pub enum ImportDirectiveSubclass<'a> {
SingleImport {
target: Name,
source: Name,
- type_determined: Cell<bool>,
- value_determined: Cell<bool>,
+ value_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
+ type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
},
GlobImport { is_prelude: bool },
}
-impl ImportDirectiveSubclass {
+impl<'a> ImportDirectiveSubclass<'a> {
pub fn single(target: Name, source: Name) -> Self {
SingleImport {
target: target,
source: source,
- type_determined: Cell::new(false),
- value_determined: Cell::new(false),
+ type_result: Cell::new(Err(Undetermined)),
+ value_result: Cell::new(Err(Undetermined)),
}
}
}
#[derive(Debug,Clone)]
pub struct ImportDirective<'a> {
pub id: NodeId,
+ parent: Module<'a>,
module_path: Vec<Name>,
- target_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
- subclass: ImportDirectiveSubclass,
+ imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
+ subclass: ImportDirectiveSubclass<'a>,
span: Span,
- vis: ty::Visibility, // see note in ImportResolutionPerNamespace about how to use this
+ vis: Cell<ty::Visibility>,
}
impl<'a> ImportDirective<'a> {
_ => None, // The binding could be shadowed by a single import, so it is not known.
})
}
+}
+
+impl<'a> Resolver<'a> {
+ fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace)
+ -> &'a RefCell<NameResolution<'a>> {
+ *module.resolutions.borrow_mut().entry((name, ns))
+ .or_insert_with(|| self.arenas.alloc_name_resolution())
+ }
+
+ /// Attempts to resolve the supplied name in the given module for the given namespace.
+ /// If successful, returns the binding corresponding to the name.
+ /// Invariant: if `record_used` is `Some`, import resolution must be complete.
+ pub fn resolve_name_in_module(&mut self,
+ module: Module<'a>,
+ name: Name,
+ ns: Namespace,
+ allow_private_imports: bool,
+ record_used: Option<Span>)
+ -> ResolveResult<&'a NameBinding<'a>> {
+ self.populate_module_if_necessary(module);
+
+ let resolution = self.resolution(module, name, ns);
+ let resolution = match resolution.borrow_state() {
+ ::std::cell::BorrowState::Unused => resolution.borrow_mut(),
+ _ => return Failed(None), // This happens when there is a cycle of imports
+ };
+
+ let is_disallowed_private_import = |binding: &NameBinding| {
+ !allow_private_imports && !binding.is_pseudo_public() && binding.is_import()
+ };
+
+ if let Some(span) = record_used {
+ if let Some(binding) = resolution.binding {
+ if is_disallowed_private_import(binding) {
+ return Failed(None);
+ }
+ self.record_use(name, ns, binding);
+ if !self.is_accessible(binding.vis) {
+ self.privacy_errors.push(PrivacyError(span, name, binding));
+ }
+ }
+
+ return resolution.binding.map(Success).unwrap_or(Failed(None));
+ }
+
+ // If the resolution doesn't depend on glob definability, check privacy and return.
+ if let Some(result) = self.try_result(&resolution, ns) {
+ return result.and_then(|binding| {
+ if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) {
+ Success(binding)
+ } else {
+ Failed(None)
+ }
+ });
+ }
+
+ // Check if the globs are determined
+ for directive in module.globs.borrow().iter() {
+ if self.is_accessible(directive.vis.get()) {
+ if let Some(module) = directive.imported_module.get() {
+ let result = self.resolve_name_in_module(module, name, ns, true, None);
+ if let Indeterminate = result {
+ return Indeterminate;
+ }
+ } else {
+ return Indeterminate;
+ }
+ }
+ }
+
+ Failed(None)
+ }
// Returns Some(the resolution of the name), or None if the resolution depends
// on whether more globs can define the name.
- fn try_result(&self, ns: Namespace, allow_private_imports: bool)
+ fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace)
-> Option<ResolveResult<&'a NameBinding<'a>>> {
- match self.binding {
+ match resolution.binding {
Some(binding) if !binding.is_glob_import() =>
- return Some(Success(binding)),
- _ => {} // Items and single imports are not shadowable
+ return Some(Success(binding)), // Items and single imports are not shadowable.
+ _ => {}
};
// Check if a single import can still define the name.
- match self.single_imports {
- SingleImports::None => {},
+ match resolution.single_imports {
SingleImports::AtLeastOne => return Some(Indeterminate),
- SingleImports::MaybeOne(directive) => {
- // If (1) we don't allow private imports, (2) no public single import can define
- // the name, and (3) no public glob has defined the name, the resolution depends
- // on whether more globs can define the name.
- if !allow_private_imports && directive.vis != ty::Visibility::Public &&
- !self.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
- return None;
- }
-
- let target_module = match directive.target_module.get() {
- Some(target_module) => target_module,
+ SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
+ let module = match directive.imported_module.get() {
+ Some(module) => module,
None => return Some(Indeterminate),
};
let name = match directive.subclass {
SingleImport { source, .. } => source,
GlobImport { .. } => unreachable!(),
};
- match target_module.resolve_name(name, ns, false) {
+ match self.resolve_name_in_module(module, name, ns, true, None) {
Failed(_) => {}
_ => return Some(Indeterminate),
}
}
+ SingleImports::MaybeOne(_) | SingleImports::None => {},
}
- self.binding.map(Success)
- }
-}
-
-impl<'a> ::ModuleS<'a> {
- fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
- *self.resolutions.borrow_mut().entry((name, ns))
- .or_insert_with(|| self.arenas.alloc_name_resolution())
+ resolution.binding.map(Success)
}
- pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
- -> ResolveResult<&'a NameBinding<'a>> {
- let resolution = self.resolution(name, ns);
- let resolution = match resolution.borrow_state() {
- ::std::cell::BorrowState::Unused => resolution.borrow_mut(),
- _ => return Failed(None), // This happens when there is a cycle of imports
- };
-
- if let Some(result) = resolution.try_result(ns, allow_private_imports) {
- // If the resolution doesn't depend on glob definability, check privacy and return.
- return result.and_then(|binding| {
- let allowed = allow_private_imports || !binding.is_import() ||
- binding.is_pseudo_public();
- if allowed { Success(binding) } else { Failed(None) }
- });
- }
-
- // Check if the globs are determined
- for directive in self.globs.borrow().iter() {
- if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
- match directive.target_module.get() {
- None => return Indeterminate,
- Some(target_module) => match target_module.resolve_name(name, ns, false) {
- Indeterminate => return Indeterminate,
- _ => {}
- }
- }
- }
-
- Failed(None)
- }
-
- pub fn add_import_directive(&self,
+ // Add an import directive to the current module.
+ pub fn add_import_directive(&mut self,
module_path: Vec<Name>,
- subclass: ImportDirectiveSubclass,
+ subclass: ImportDirectiveSubclass<'a>,
span: Span,
id: NodeId,
vis: ty::Visibility) {
+ let current_module = self.current_module;
let directive = self.arenas.alloc_import_directive(ImportDirective {
+ parent: current_module,
module_path: module_path,
- target_module: Cell::new(None),
+ imported_module: Cell::new(None),
subclass: subclass,
span: span,
id: id,
- vis: vis,
+ vis: Cell::new(vis),
});
- self.unresolved_imports.borrow_mut().push(directive);
+ self.indeterminate_imports.push(directive);
match directive.subclass {
SingleImport { target, .. } => {
for &ns in &[ValueNS, TypeNS] {
- self.resolution(target, ns).borrow_mut().single_imports
- .add_directive(directive);
+ let mut resolution = self.resolution(current_module, target, ns).borrow_mut();
+ resolution.single_imports.add_directive(directive);
}
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
// which are not relevant to import resolution.
GlobImport { is_prelude: true } => {}
- GlobImport { .. } => self.globs.borrow_mut().push(directive),
+ GlobImport { .. } => self.current_module.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>)
directive: directive,
},
span: directive.span,
- vis: directive.vis,
+ vis: directive.vis.get(),
}
}
// 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 *module.resolution(name, ns).borrow_mut();
+ let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
let was_known = resolution.binding().is_some();
let t = f(self, resolution);
// 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() {
+ for 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);
+ let _ = self.try_define(directive.parent, name, ns, imported_binding);
}
}
}
}
-struct ImportResolvingError<'a> {
- /// Module where the error happened
- source_module: Module<'a>,
- import_directive: &'a ImportDirective<'a>,
- span: Span,
- help: String,
-}
-
struct ImportResolver<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
}
// remain or unsuccessfully when no forward progress in resolving imports
// is made.
+ fn set_current_module(&mut self, module: Module<'b>) {
+ self.current_module = module;
+ self.current_vis = ty::Visibility::Restricted({
+ let normal_module = self.get_nearest_normal_module_parent_or_self(module);
+ self.definitions.as_local_node_id(normal_module.def_id().unwrap()).unwrap()
+ });
+ }
+
/// Resolves all imports for the crate. This method performs the fixed-
/// point iteration.
fn resolve_imports(&mut self) {
let mut i = 0;
- let mut prev_unresolved_imports = 0;
- let mut errors = Vec::new();
+ let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
- loop {
- debug!("(resolving imports) iteration {}, {} imports left", i, self.unresolved_imports);
+ while self.indeterminate_imports.len() < prev_num_indeterminates {
+ prev_num_indeterminates = self.indeterminate_imports.len();
+ debug!("(resolving imports) iteration {}, {} imports left", i, prev_num_indeterminates);
- // Attempt to resolve imports in all local modules.
- for module in self.arenas.local_modules().iter() {
- self.current_module = module;
- self.resolve_imports_in_current_module(&mut errors);
- }
+ let mut imports = Vec::new();
+ ::std::mem::swap(&mut imports, &mut self.indeterminate_imports);
- if self.unresolved_imports == 0 {
- debug!("(resolving imports) success");
- for module in self.arenas.local_modules().iter() {
- self.finalize_resolutions_in(module, false);
+ for import in imports {
+ match self.resolve_import(&import) {
+ Failed(_) => self.determined_imports.push(import),
+ Indeterminate => self.indeterminate_imports.push(import),
+ Success(()) => self.determined_imports.push(import),
}
- break;
}
- 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.arenas.local_modules().iter() {
- self.finalize_resolutions_in(module, errors.len() == 0);
- }
- for e in errors {
- self.import_resolving_error(e)
- }
- break;
+ i += 1;
+ }
+
+ for module in self.arenas.local_modules().iter() {
+ self.finalize_resolutions_in(module);
+ }
+
+ let mut errors = false;
+ for i in 0 .. self.determined_imports.len() {
+ let import = self.determined_imports[i];
+ if let Failed(err) = self.finalize_import(import) {
+ errors = true;
+ let (span, help) = match err {
+ Some((span, msg)) => (span, msg),
+ None => (import.span, String::new()),
+ };
+
+ // 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(import);
+ let path = import_path_to_string(&import.module_path, &import.subclass);
+ let error = ResolutionError::UnresolvedImport(Some((&path, &help)));
+ resolve_error(self.resolver, span, error);
}
+ }
- i += 1;
- prev_unresolved_imports = self.unresolved_imports;
+ // Report unresolved imports only if no hard error was already reported
+ // to avoid generating multiple errors on the same import.
+ if !errors {
+ if let Some(import) = self.indeterminate_imports.iter().next() {
+ let error = ResolutionError::UnresolvedImport(None);
+ resolve_error(self.resolver, import.span, error);
+ }
}
}
// Define a "dummy" resolution containing a Def::Err as a placeholder for a
// failed resolution
- fn import_dummy_binding(&mut self,
- source_module: Module<'b>,
- directive: &'b ImportDirective<'b>) {
+ fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) {
if let SingleImport { target, .. } = directive.subclass {
let dummy_binding = self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Def(Def::Err),
});
let dummy_binding = self.import(dummy_binding, directive);
- 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(&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);
- let path = import_path_to_string(&e.import_directive.module_path,
- &e.import_directive.subclass);
- resolve_error(self.resolver,
- e.span,
- ResolutionError::UnresolvedImport(Some((&path, &e.help))));
- }
-
- /// 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.current_module.unresolved_imports.borrow_mut();
- ::std::mem::swap(&mut imports, &mut unresolved_imports);
-
- for import_directive in imports {
- match self.resolve_import(&import_directive) {
- Failed(err) => {
- let (span, help) = match err {
- Some((span, msg)) => (span, format!(". {}", msg)),
- None => (import_directive.span, String::new()),
- };
- errors.push(ImportResolvingError {
- 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.unresolved_imports >= 1);
- self.unresolved_imports -= 1;
- }
- }
+ let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone());
+ let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding);
}
}
names_to_string(&directive.module_path),
module_to_string(self.current_module));
- let target_module = match directive.target_module.get() {
- Some(module) => module,
- _ => match self.resolve_module_path(&directive.module_path,
- DontUseLexicalScope,
- directive.span) {
+ self.set_current_module(directive.parent);
+
+ let module = if let Some(module) = directive.imported_module.get() {
+ module
+ } else {
+ let vis = directive.vis.get();
+ // For better failure detection, pretend that the import will not define any names
+ // while resolving its module path.
+ directive.vis.set(ty::Visibility::PrivateExternal);
+ let result =
+ self.resolve_module_path(&directive.module_path, DontUseLexicalScope, None);
+ directive.vis.set(vis);
+
+ match result {
Success(module) => module,
Indeterminate => return Indeterminate,
Failed(err) => return Failed(err),
- },
+ }
};
- directive.target_module.set(Some(target_module));
- let (source, target, value_determined, type_determined) = match directive.subclass {
- SingleImport { source, target, ref value_determined, ref type_determined } =>
- (source, target, value_determined, type_determined),
- GlobImport { .. } => return self.resolve_glob_import(target_module, directive),
+ directive.imported_module.set(Some(module));
+ let (source, target, value_result, type_result) = match directive.subclass {
+ SingleImport { source, target, ref value_result, ref type_result } =>
+ (source, target, value_result, type_result),
+ GlobImport { .. } => {
+ self.resolve_glob_import(directive);
+ return Success(());
+ }
};
- // We need to resolve both namespaces for this to succeed.
- 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.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);
- self.update_resolution(module, target, ns, |_, resolution| {
+ let mut indeterminate = false;
+ for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
+ if let Err(Undetermined) = result.get() {
+ result.set({
+ match self.resolve_name_in_module(module, source, ns, false, None) {
+ Success(binding) => Ok(binding),
+ Indeterminate => Err(Undetermined),
+ Failed(_) => Err(Determined),
+ }
+ });
+ } else {
+ continue
+ };
+
+ match result.get() {
+ Err(Undetermined) => indeterminate = true,
+ Err(Determined) => {
+ self.update_resolution(directive.parent, target, ns, |_, resolution| {
resolution.single_imports.directive_failed()
});
}
- Success(binding) if !binding.is_importable() => {
+ Ok(binding) if !binding.is_importable() => {
let msg = format!("`{}` is not directly importable", target);
struct_span_err!(self.session, directive.span, E0253, "{}", &msg)
.span_label(directive.span, &format!("cannot be imported directly"))
.emit();
// 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(directive);
return Success(());
}
- Success(binding) if !self.is_accessible(binding.vis) => {}
- Success(binding) if !determined.get() => {
- determined.set(true);
+ Ok(binding) => {
let imported_binding = self.import(binding, directive);
- let conflict = self.try_define(module, target, ns, imported_binding);
+ let conflict = self.try_define(directive.parent, target, ns, imported_binding);
if let Err(old_binding) = conflict {
let binding = &self.import(binding, directive);
- self.report_conflict(module, target, ns, binding, old_binding);
+ self.report_conflict(directive.parent, target, ns, binding, old_binding);
}
- privacy_error = false;
}
- Success(_) => privacy_error = false,
- _ => {}
}
}
- match (&value_result, &type_result) {
- (&Indeterminate, _) | (_, &Indeterminate) => return Indeterminate,
- (&Failed(_), &Failed(_)) => {
- let resolutions = target_module.resolutions.borrow();
- let names = resolutions.iter().filter_map(|(&(ref name, _), resolution)| {
- if *name == source { return None; } // Never suggest the same name
+ if indeterminate { Indeterminate } else { Success(()) }
+ }
+
+ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
+ self.set_current_module(directive.parent);
+
+ let ImportDirective { ref module_path, span, .. } = *directive;
+ let module_result = self.resolve_module_path(&module_path, DontUseLexicalScope, Some(span));
+ let module = match module_result {
+ Success(module) => module,
+ Indeterminate => return Indeterminate,
+ Failed(err) => return Failed(err),
+ };
+
+ let (name, value_result, type_result) = match directive.subclass {
+ SingleImport { source, ref value_result, ref type_result, .. } =>
+ (source, value_result.get(), type_result.get()),
+ GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
+ // Importing a module into itself is not allowed.
+ let msg = "Cannot glob-import a module into itself.".into();
+ return Failed(Some((directive.span, msg)));
+ }
+ GlobImport { .. } => return Success(()),
+ };
+
+ for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
+ if let Ok(binding) = result {
+ self.record_use(name, ns, binding);
+ }
+ }
+
+ if value_result.is_err() && type_result.is_err() {
+ let (value_result, type_result);
+ value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span));
+ type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span));
+
+ return if let (Failed(_), Failed(_)) = (value_result, type_result) {
+ let resolutions = module.resolutions.borrow();
+ let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
+ if *n == name { return None; } // Never suggest the same name
match *resolution.borrow() {
- NameResolution { binding: Some(_), .. } => Some(name),
+ NameResolution { binding: Some(_), .. } => Some(n),
NameResolution { single_imports: SingleImports::None, .. } => None,
- _ => Some(name),
+ _ => Some(n),
}
});
- let lev_suggestion = match find_best_match_for_name(names, &source.as_str(), None) {
+ let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) {
Some(name) => format!(". Did you mean to use `{}`?", name),
None => "".to_owned(),
};
- let module_str = module_to_string(target_module);
+ let module_str = module_to_string(module);
let msg = if &module_str == "???" {
- format!("There is no `{}` in the crate root{}", source, lev_suggestion)
+ format!("no `{}` in the root{}", name, lev_suggestion)
} else {
- format!("There is no `{}` in `{}`{}", source, module_str, lev_suggestion)
+ format!("no `{}` in `{}`{}", name, module_str, lev_suggestion)
};
- return Failed(Some((directive.span, msg)));
- }
- _ => (),
- }
-
- if privacy_error {
- for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] {
- let binding = match *result { Success(binding) => binding, _ => continue };
- 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);
+ Failed(Some((directive.span, msg)))
+ } else {
+ // `resolve_name_in_module` reported a privacy error.
+ self.import_dummy_binding(directive);
+ Success(())
}
}
- match (&value_result, &type_result) {
- (&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);
+ match (value_result, type_result) {
+ (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
+ let msg = format!("`{}` is private, and cannot be reexported", name);
+ let note_msg =
+ format!("consider marking `{}` as `pub` in the imported module", name);
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) &&
- self.is_accessible(binding.vis) => {
+ (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
if binding.is_extern_crate() {
let msg = format!("extern crate `{}` is private, and cannot be reexported \
(error E0364), consider declaring with `pub`",
- source);
+ name);
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
} else {
- let mut err = struct_span_err!(self.session, directive.span, E0365,
- "`{}` is private, and cannot be reexported",
- source);
- err.span_label(directive.span, &format!("reexport of private `{}`", source));
- err.note(&format!("consider declaring type or module `{}` with `pub`", source));
- err.emit();
+ struct_span_err!(self.session, directive.span, E0365,
+ "`{}` is private, and cannot be reexported", name)
+ .span_label(directive.span, &format!("reexport of private `{}`", name))
+ .note(&format!("consider declaring type or module `{}` with `pub`", name))
+ .emit();
}
}
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
- let def = match type_result.success().and_then(NameBinding::def) {
+ let def = match type_result.ok().and_then(NameBinding::def) {
Some(def) => def,
- None => value_result.success().and_then(NameBinding::def).unwrap(),
+ None => value_result.ok().and_then(NameBinding::def).unwrap(),
};
let path_resolution = PathResolution::new(def);
self.def_map.insert(directive.id, path_resolution);
return Success(());
}
- // Resolves a glob import. Note that this function cannot fail; it either
- // succeeds or bails out (as importing * from an empty module or a module
- // that exports nothing is valid). target_module is the module we are
- // actually importing, i.e., `foo` in `use foo::*`.
- fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>)
- -> ResolveResult<()> {
- if let Some(Def::Trait(_)) = target_module.def {
- self.session.span_err(directive.span, "items in traits are not importable.");
- }
+ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
+ let module = directive.imported_module.get().unwrap();
+ self.populate_module_if_necessary(module);
- 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)));
+ if let Some(Def::Trait(_)) = module.def {
+ self.session.span_err(directive.span, "items in traits are not importable.");
}
- self.populate_module_if_necessary(target_module);
- if let GlobImport { is_prelude: true } = directive.subclass {
- self.prelude = Some(target_module);
- return Success(());
+ if module.def_id() == directive.parent.def_id() {
+ return;
+ } else if let GlobImport { is_prelude: true } = directive.subclass {
+ self.prelude = Some(module);
+ return;
}
- // Add to target_module's glob_importers
- target_module.glob_importers.borrow_mut().push((module, directive));
+ // Add to module's glob_importers
+ module.glob_importers.borrow_mut().push(directive);
// 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)| {
+ let bindings = 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 imported_binding = self.import(binding, directive);
- let _ = self.try_define(module, name, ns, imported_binding);
+ let _ = self.try_define(directive.parent, name, ns, imported_binding);
}
}
// Record the destination of this import
- if let Some(did) = target_module.def_id() {
+ if let Some(did) = module.def_id() {
let resolution = PathResolution::new(Def::Mod(did));
self.def_map.insert(directive.id, resolution);
}
-
- debug!("(resolving glob import) successfully resolved import");
- return Success(());
}
// Miscellaneous post-processing, including recording reexports, reporting conflicts,
// reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
- fn finalize_resolutions_in(&mut self, module: Module<'b>, report_unresolved_imports: bool) {
+ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
// Since import resolution is finished, globs will not define any more names.
*module.globs.borrow_mut() = Vec::new();
self.export_map.insert(node_id, reexports);
}
}
-
- if report_unresolved_imports {
- for import in module.unresolved_imports.borrow().iter() {
- resolve_error(self.resolver, import.span, ResolutionError::UnresolvedImport(None));
- break;
- }
- }
}
}
return
}
+ let mut arg = OsString::new();
let path = tmpdir.join("list");
- let prefix = if self.sess.target.target.options.is_like_osx {
- "_"
- } else {
- ""
- };
- let res = (|| -> io::Result<()> {
- let mut f = BufWriter::new(File::create(&path)?);
- for sym in &self.info.cdylib_exports {
- writeln!(f, "{}{}", prefix, sym)?;
+
+ if self.sess.target.target.options.is_like_solaris {
+ let res = (|| -> io::Result<()> {
+ let mut f = BufWriter::new(File::create(&path)?);
+ writeln!(f, "{{\n global:")?;
+ for sym in &self.info.cdylib_exports {
+ writeln!(f, " {};", sym)?;
+ }
+ writeln!(f, "\n local:\n *;\n}};")?;
+ Ok(())
+ })();
+ if let Err(e) = res {
+ self.sess.fatal(&format!("failed to write version script: {}", e));
}
- Ok(())
- })();
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write lib.def file: {}", e));
- }
- let mut arg = OsString::new();
- if self.sess.target.target.options.is_like_osx {
- arg.push("-Wl,-exported_symbols_list,");
+
+ arg.push("-Wl,-M,");
+ arg.push(&path);
} else {
- arg.push("-Wl,--retain-symbols-file=");
+ let prefix = if self.sess.target.target.options.is_like_osx {
+ "_"
+ } else {
+ ""
+ };
+ let res = (|| -> io::Result<()> {
+ let mut f = BufWriter::new(File::create(&path)?);
+ for sym in &self.info.cdylib_exports {
+ writeln!(f, "{}{}", prefix, sym)?;
+ }
+ Ok(())
+ })();
+ if let Err(e) = res {
+ self.sess.fatal(&format!("failed to write lib.def file: {}", e));
+ }
+ if self.sess.target.target.options.is_like_osx {
+ arg.push("-Wl,-exported_symbols_list,");
+ } else {
+ arg.push("-Wl,--retain-symbols-file=");
+ }
+ arg.push(&path);
}
- arg.push(&path);
+
self.cmd.arg(arg);
}
}
if let ty::TyTrait(..) = mt.ty.sty {
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
- span_err!(self.tcx.sess, span, E0033,
- "type `{}` cannot be dereferenced",
- self.ty_to_string(expected));
+ let type_str = self.ty_to_string(expected);
+ struct_span_err!(self.tcx.sess, span, E0033,
+ "type `{}` cannot be dereferenced", type_str)
+ .span_label(span, &format!("type `{}` cannot be dereferenced", type_str))
+ .emit();
return false
}
}
}
CastError::CastToBool => {
struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
+ .span_label(self.span, &format!("unsupported cast"))
.help("compare with zero instead")
.emit();
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+ v.reserve_exact(1);
v.push(0);
CString { inner: v.into_boxed_slice() }
}
// We roughly maintain the deadlocking behavior by panicking to ensure
// that this lock acquisition does not succeed.
//
- // We also check whether there this lock is already write locked. This
+ // We also check whether this lock is already write locked. This
// is only possible if it was write locked by the current thread and
// the implementation allows recursive locking. The POSIX standard
- // doesn't require recursivly locking a rwlock to deadlock, but we can't
+ // doesn't require recursively locking a rwlock to deadlock, but we can't
// allow that because it could lead to aliasing issues.
if r == libc::EAGAIN {
panic!("rwlock maximum reader count exceeded");
//~| ERROR E0017
//~| NOTE statics require immutable values
//~| ERROR E0388
+ //~| NOTE cannot write data in a static definition
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
//~| NOTE statics require immutable values
//~| ERROR E0017
}
fn main() {
- let trait_obj: &SomeTrait = SomeTrait; //~ ERROR E0425
- //~^ ERROR E0038
- let &invalid = trait_obj; //~ ERROR E0033
+ let trait_obj: &SomeTrait = SomeTrait;
+ //~^ ERROR E0425
+ //~| ERROR E0038
+ //~| method `foo` has no receiver
+ //~| NOTE the trait `SomeTrait` cannot be made into an object
+
+ let &invalid = trait_obj;
+ //~^ ERROR E0033
+ //~| NOTE type `&SomeTrait` cannot be dereferenced
}
struct Foo { a: bool };
let f = Foo(); //~ ERROR E0423
+ //~^ struct called like a function
}
fn bar(self) {}
fn foo() {
- self.bar(); //~ ERROR E0424
+ self.bar();
+ //~^ ERROR `self` is not available in a static method [E0424]
+ //~| NOTE not available in static method
+ //~| NOTE maybe a `self` argument is missing?
}
}
fn main () {
loop {
- break 'a; //~ ERROR E0426
+ break 'a;
+ //~^ ERROR E0426
+ //~| NOTE undeclared label `'a`
}
}
fn main () {
let foo = 42u32;
const FOO : u32 = foo; //~ ERROR E0435
+ //~| NOTE non-constant used with constant
}
impl Foo for i32 {
type Bar = bool; //~ ERROR E0437
+ //~| NOTE not a member of trait `Foo`
}
fn main () {
impl Foo for i32 {
const BAR: bool = true; //~ ERROR E0438
+ //~| NOTE not a member of trait `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.
+
+#![feature(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+extern "platform-intrinsic" {
+ fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441
+}
+
+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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
+ i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+struct i64x2(i64, i64);
+
+extern "platform-intrinsic" {
+ fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2;
+ //~^ ERROR E0442
+ //~| ERROR E0442
+ //~| ERROR E0442
+}
+
+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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64);
+
+extern "platform-intrinsic" {
+ fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443
+}
+
+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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct f64x2(f64, f64);
+
+extern "platform-intrinsic" {
+ fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E0444
+}
+
+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.
+
+trait Foo {
+ fn dummy(&self) { }
+}
+
+pub trait Bar : Foo {} //~ ERROR E0445
+pub struct Bar2<T: Foo>(pub T); //~ ERROR E0445
+pub fn foo<T: Foo> (t: T) {} //~ ERROR E0445
+
+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 {
+ struct Bar(u32);
+
+ pub fn bar() -> Bar { //~ ERROR E0446
+ Bar(0)
+ }
+}
+
+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.
+
+struct Bar;
+
+trait Foo {
+ fn foo();
+}
+
+pub impl Bar {} //~ ERROR E0449
+
+pub impl Foo for Bar { //~ ERROR E0449
+ pub fn foo() {} //~ ERROR E0449
+}
+
+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 Bar {
+ pub struct Foo(isize);
+}
+
+fn main() {
+ let f = Bar::Foo(0); //~ ERROR E0450
+}
--- /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 Bar {
+ pub struct Foo {
+ pub a: isize,
+ b: isize,
+ }
+}
+
+fn main() {
+ let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451
+}
--- /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.
+
+#![allow(foo = "")] //~ ERROR E0452
+
+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.
+
+#![forbid(non_snake_case)]
+
+#[allow(non_snake_case)] //~ ERROR E0453
+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.
+
+#[link(name = "")] extern {} //~ ERROR E0454
+
+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.
+
+#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458
+ //~^ ERROR E0459
+
+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.
+
+#[link(kind = "dylib")] extern {} //~ ERROR E0459
+
+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(plugin)]
+#![plugin(cookie_monster)] //~ ERROR E0463
+extern crate cake_is_a_lie;
+
+fn main() {
+}
let _x = &mut a.x;
//~^ NOTE borrow of `a.x` occurs here
let _y = a.y; //~ ERROR cannot use
+ //~^ NOTE use of borrowed `a.x`
}
fn move_after_mut_borrow() {
let _x = &mut a.x.x;
//~^ NOTE borrow of `a.x.x` occurs here
let _y = a.y; //~ ERROR cannot use
+ //~^ NOTE use of borrowed `a.x.x`
}
fn move_after_mut_borrow_nested() {
//~^ ERROR casting
//~^^ HELP through a usize first
let _ = 3_i32 as bool;
- //~^ ERROR cannot cast as `bool`
+ //~^ ERROR cannot cast as `bool` [E0054]
+ //~| unsupported cast
//~| HELP compare with zero
let _ = E::A as bool;
- //~^ ERROR cannot cast as `bool`
+ //~^ ERROR cannot cast as `bool` [E0054]
+ //~| unsupported cast
//~| HELP compare with zero
let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use spam::{ham, eggs};
-//~^ ERROR unresolved import `spam::eggs`. There is no `eggs` in `spam`
+use spam::{ham, eggs}; //~ ERROR unresolved import `spam::eggs` [E0432]
+ //~^ no `eggs` in `spam`
mod spam {
pub fn ham() { }
// except according to those terms.
use zed::bar;
-use zed::baz;
-//~^ ERROR unresolved import `zed::baz`. There is no `baz` in `zed`
+use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
+ //~^ no `baz` in `zed`. Did you mean to use `bar`?
mod zed {
pub fn bar() { println!("bar"); }
- use foo; //~ ERROR unresolved import
+ use foo; //~ ERROR unresolved import `foo` [E0432]
+ //~^ no `foo` in the root
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use baz::zed::bar;
-//~^ ERROR unresolved import `baz::zed::bar`. Could not find `zed` in `baz`
+use baz::zed::bar; //~ ERROR unresolved import `baz::zed::bar` [E0432]
+ //~^ Could not find `zed` in `baz`
mod baz {}
mod zed {
use foo::bar;
mod test {
- use bar::foo;
- //~^ ERROR unresolved import `bar::foo`. Maybe a missing `extern crate bar`?
+ use bar::foo; //~ ERROR unresolved import `bar::foo` [E0432]
+ //~^ Maybe a missing `extern crate bar`?
}
fn main() {}
// except according to those terms.
use a::f;
-use b::f;
-//~^ ERROR: unresolved import `b::f`. There is no `f` in `b`
+use b::f; //~ ERROR: unresolved import `b::f` [E0432]
+ //~^ no `f` in `b`
mod a { pub fn f() {} }
mod b { }
// Testing that we don't fail abnormally after hitting the errors
-use unresolved::*; //~ ERROR unresolved import `unresolved::*`. Maybe a missing `extern crate unres
+use unresolved::*; //~ ERROR unresolved import `unresolved::*` [E0432]
+ //~^ Maybe a missing `extern crate unresolved`?
fn main() {}
}
fn main() {
- let f = Foo::Variant(42); //~ ERROR uses it like a function
+ let f = Foo::Variant(42);
+ //~^ ERROR uses it like a function
+ //~| struct called like a function
}
}
fn main() {
- let homura = Homura::Madoka; //~ ERROR uses it like a function
+ let homura = Homura::Madoka;
+ //~^ ERROR uses it like a function
+ //~| struct called like a function
}
impl cat {
fn meow() {
if self.whiskers > 3 {
- //~^ ERROR: `self` is not available in a static method. Maybe a `self` argument is missing?
+ //~^ ERROR `self` is not available in a static method [E0424]
+ //~| NOTE not available in static method
+ //~| NOTE maybe a `self` argument is missing?
println!("MEOW");
}
}
($this:expr) => {
$this.width.unwrap()
//~^ ERROR cannot use `self.width` because it was mutably borrowed
+ //~| NOTE use of borrowed `*self`
}
);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use m::f as x; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
+use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
+ //~^ no `f` in `m`
mod m {}
// except according to those terms.
type Alias = ();
-use Alias::*; //~ ERROR Not a module
-use std::io::Result::*; //~ ERROR Not a module
+use Alias::*;
+//~^ ERROR unresolved import `Alias::*` [E0432]
+//~| Not a module `Alias`
+use std::io::Result::*;
+//~^ ERROR unresolved import `std::io::Result::*` [E0432]
+//~| Not a module `Result`
trait T {}
use T::*; //~ ERROR items in traits are not importable
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use bar::Foo; //~ ERROR There is no `Foo` in `bar` [E0432]
+use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
+ //~^ no `Foo` in `bar`
mod bar {
- use Foo; //~ ERROR There is no `Foo` in the crate root [E0432]
+ use Foo; //~ ERROR unresolved import `Foo` [E0432]
+ //~^ no `Foo` in the root
}
fn main() {}
//~| NOTE: not a trait
//~| NOTE: aliases cannot be used for traits
-use ImportError; //~ ERROR unresolved
+use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
+ //~^ no `ImportError` in the root
impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use self::*; //~ ERROR: unresolved import `self::*`. Cannot glob-import a module into itself.
+use self::*; //~ ERROR: unresolved import `self::*` [E0432]
+ //~^ Cannot glob-import a module into itself.
mod foo {
- use foo::*; //~ ERROR: unresolved import `foo::*`. Cannot glob-import a module into itself.
+ use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
+ //~^ Cannot glob-import a module into itself.
mod bar {
use super::bar::*;
- //~^ ERROR: unresolved import `super::bar::*`. Cannot glob-import a module into itself.
+ //~^ ERROR: unresolved import `super::bar::*` [E0432]
+ //~| Cannot glob-import a module into itself.
}
}
fn test1() {
use bar::foo;
- //~^ ERROR unresolved import `bar::foo`. There is no `foo` in `bar`
+ //~^ ERROR unresolved import `bar::foo` [E0432]
+ //~| no `foo` in `bar`
}
fn test2() {
use bar::glob::foo;
- //~^ ERROR unresolved import `bar::glob::foo`. There is no `foo` in `bar::glob`
+ //~^ ERROR unresolved import `bar::glob::foo` [E0432]
+ //~| no `foo` in `bar::glob`
}
#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
fn test1() {
use bar::gpriv;
- //~^ ERROR unresolved import `bar::gpriv`. There is no `gpriv` in `bar`
+ //~^ ERROR unresolved import `bar::gpriv` [E0432]
+ //~| no `gpriv` in `bar`
// This should pass because the compiler will insert a fake name binding
// for `gpriv`
--- /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(question_mark, question_mark_carrier)]
+
+// Test that type inference fails where there are multiple possible return types
+// for the `?` operator.
+
+fn f(x: &i32) -> Result<i32, ()> {
+ Ok(*x)
+}
+
+fn g() -> Result<Vec<i32>, ()> {
+ let l = [1, 2, 3, 4];
+ l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve
+}
+
+fn main() {
+ g();
+}
fn broken() {
let mut x = 3;
let mut _y = vec!(&mut x);
+ //~^ NOTE borrow of `x` occurs here
+ //~| NOTE borrow of `x` occurs here
+ //~| NOTE borrow of `x` occurs here
while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
+ //~^ NOTE use of borrowed `x`
let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
+ //~^ NOTE use of borrowed `x`
_y.push(&mut z); //~ ERROR `z` does not live long enough
+ //~^ NOTE does not live long enough
x += 1; //~ ERROR cannot assign
+ //~^ NOTE assignment to borrowed `x` occurs here
}
+ //~^ NOTE borrowed value only valid until here
}
+//~^ NOTE borrowed value must be valid until here
fn main() { }
mod a {
extern crate collections;
use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `self::collections`?
+ //~^ ERROR unresolved import `collections::HashMap` [E0432]
+ //~| Did you mean `self::collections`?
mod b {
use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+ //~^ ERROR unresolved import `collections::HashMap` [E0432]
+ //~| Did you mean `a::collections`?
mod c {
use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+ //~^ ERROR unresolved import `collections::HashMap` [E0432]
+ //~| Did you mean `a::collections`?
mod d {
use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+ //~^ ERROR unresolved import `collections::HashMap` [E0432]
+ //~| Did you mean `a::collections`?
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::f; //~ ERROR unresolved import `super::f`. There are too many initial `super`s.
+use super::f; //~ ERROR unresolved import `super::f` [E0432]
+ //~^ There are too many initial `super`s.
fn main() {
}
pub fn main() {
test_send::<rand::ThreadRng>();
- //~^ ERROR : std::marker::Send` is not satisfied
}
// ignore-tidy-linelength
-use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern crate foo`?
+use foo::bar; //~ ERROR unresolved import `foo::bar` [E0432]
+ //~^ Maybe a missing `extern crate foo`?
-use bar::Baz as x; //~ ERROR unresolved import `bar::Baz`. There is no `Baz` in `bar`. Did you mean to use `Bar`?
+use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
+ //~^ no `Baz` in `bar`. Did you mean to use `Bar`?
-use food::baz; //~ ERROR unresolved import `food::baz`. There is no `baz` in `food`. Did you mean to use `bag`?
+use food::baz; //~ ERROR unresolved import `food::baz`
+ //~^ no `baz` in `food`. Did you mean to use `bag`?
-use food::{beens as Foo}; //~ ERROR unresolved import `food::beens`. There is no `beens` in `food`. Did you mean to use `beans`?
+use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432]
+ //~^ no `beens` in `food`. Did you mean to use `beans`?
mod bar {
pub struct Bar;
use use_from_trait_xc::Trait::CONST;
//~^ ERROR `CONST` is not directly importable
-use use_from_trait_xc::Foo::new;
+use use_from_trait_xc::Foo::new; //~ ERROR struct `Foo` is private
//~^ ERROR unresolved import `use_from_trait_xc::Foo::new`
-use use_from_trait_xc::Foo::C;
+use use_from_trait_xc::Foo::C; //~ ERROR struct `Foo` is private
//~^ ERROR unresolved import `use_from_trait_xc::Foo::C`
use use_from_trait_xc::Bar::new as bnew;
//~^ ERROR `C` is not directly importable
use Foo::new;
-//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
+//~^ ERROR unresolved import `Foo::new` [E0432]
+//~| Not a module `Foo`
use Foo::C2;
-//~^ ERROR unresolved import `Foo::C2`. Not a module `Foo`
+//~^ ERROR unresolved import `Foo::C2` [E0432]
+//~| Not a module `Foo`
pub trait Trait {
fn foo();
mod a {
mod b {
use self as A; //~ ERROR `self` imports are only allowed within a { } list
- //~^ ERROR unresolved import `self`. There is no `self` in the crate root
- use super as B; //~ ERROR unresolved import `super`. There is no `super` in the crate root
- use super::{self as C}; //~ERROR unresolved import `super`. There is no `super` in the crate
+ //~^ ERROR unresolved import `self` [E0432]
+ //~| no `self` in the root
+ use super as B;
+ //~^ ERROR unresolved import `super` [E0432]
+ //~| no `super` in the root
+ use super::{self as C};
+ //~^ ERROR unresolved import `super` [E0432]
+ //~| no `super` in the root
}
}
mod foo {
use self::{self};
- //~^ ERROR unresolved import `self`. There is no `self` in the crate root
+ //~^ ERROR unresolved import `self` [E0432]
+ //~| no `self` in the root
use super::{self};
- //~^ ERROR unresolved import `super`. There is no `super` in the crate root
+ //~^ ERROR unresolved import `super` [E0432]
+ //~| no `super` in the root
}
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(question_mark, question_mark_carrier)]
+
+use std::ops::Carrier;
+
+enum MyResult<T, U> {
+ Awesome(T),
+ Terrible(U)
+}
+
+impl<U, V> Carrier for MyResult<U, V> {
+ type Success = U;
+ type Error = V;
+
+ fn from_success(u: U) -> MyResult<U, V> {
+ MyResult::Awesome(u)
+ }
+
+ fn from_error(e: V) -> MyResult<U, V> {
+ MyResult::Terrible(e)
+ }
+
+ fn translate<T>(self) -> T
+ where T: Carrier<Success=U, Error=V>
+ {
+ match self {
+ MyResult::Awesome(u) => T::from_success(u),
+ MyResult::Terrible(e) => T::from_error(e),
+ }
+ }
+}
+
+fn f(x: i32) -> Result<i32, String> {
+ if x == 0 {
+ Ok(42)
+ } else {
+ let y = g(x)?;
+ Ok(y)
+ }
+}
+
+fn g(x: i32) -> MyResult<i32, String> {
+ let _y = f(x - 1)?;
+ MyResult::Terrible("Hello".to_owned())
+}
+
+fn h() -> MyResult<i32, String> {
+ let a: Result<i32, &'static str> = Err("Hello");
+ let b = a?;
+ MyResult::Awesome(b)
+}
+
+fn i() -> MyResult<i32, String> {
+ let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
+ let b = a?;
+ MyResult::Awesome(b)
+}
+
+fn main() {
+ assert!(f(0) == Ok(42));
+ assert!(f(10) == Err("Hello".to_owned()));
+ let _ = h();
+ let _ = i();
+}
#[cfg(unix)]
pub fn check(path: &Path, bad: &mut bool) {
use std::fs;
+ use std::process::{Command, Stdio};
use std::os::unix::prelude::*;
super::walk(path,
let metadata = t!(fs::symlink_metadata(&file), &file);
if metadata.mode() & 0o111 != 0 {
- println!("binary checked into source: {}", file.display());
- *bad = true;
+ let rel_path = file.strip_prefix(path).unwrap();
+ let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
+ let ret_code = Command::new("git")
+ .arg("ls-files")
+ .arg(&git_friendly_path)
+ .current_dir(path)
+ .stdout(Stdio::null())
+ .stderr(Stdio::null())
+ .status()
+ .unwrap_or_else(|e| {
+ panic!("could not run git ls-files: {}", e);
+ });
+ if ret_code.success() {
+ println!("binary checked into source: {}", file.display());
+ *bad = true;
+ }
}
})
}