The previous version using `PartialOrd::le` was broken since it passed `T` arguments where `&T` was expected.
It makes sense to use primitive comparisons since range patterns can only be used with chars and numeric types.
r? @eddyb
url = https://github.com/rust-lang/jemalloc.git
[submodule "src/rust-installer"]
path = src/rust-installer
- url = https://github.com/rust-lang/rust-installer
+ url = https://github.com/rust-lang/rust-installer.git
[submodule "src/liblibc"]
path = src/liblibc
- url = https://github.com/rust-lang/libc
+ url = https://github.com/rust-lang-nursery/libc.git
mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time.
This means that your code cannot simultaneously work on different elements of the vector from
different `Rc` handles. However, we are able to push and pop from the `Vec<T>` at will. This is
-similar to an `&mut Vec<T>` with the borrow checking done at runtime.
+similar to a `&mut Vec<T>` with the borrow checking done at runtime.
With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus,
we can independently borrow separate elements, but we cannot push or pop from the vector. This is
-similar to an `&mut [T]`[^3], but, again, the borrow checking is at runtime.
+similar to a `&mut [T]`[^3], but, again, the borrow checking is at runtime.
In concurrent programs, we have a similar situation with `Arc<Mutex<T>>`, which provides shared
mutability and ownership.
```
This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
-correct: documentation comments apply to the thing after them, and there's
+correct; documentation comments apply to the thing after them, and there's
nothing after that last comment.
[rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
```rust,ignore
/// use std::io;
-/// let mut input = String::new();
+/// let mut input = String::new();
/// try!(io::stdin().read_line(&mut input));
```
/// ```
/// use std::io;
/// # fn foo() -> io::Result<()> {
-/// let mut input = String::new();
+/// let mut input = String::new();
/// try!(io::stdin().read_line(&mut input));
/// # Ok(())
/// # }
...(x: &'a i32)
```
-If we wanted an `&mut` reference, we’d do this:
+If we wanted a `&mut` reference, we’d do this:
```rust,ignore
...(x: &'a mut i32)
`match` takes an expression and then branches based on its value. Each ‘arm’ of
the branch is of the form `val => expression`. When the value matches, that arm’s
expression will be evaluated. It’s called `match` because of the term ‘pattern
-matching’, which `match` is an implementation of. There’s an [entire section on
+matching’, which `match` is an implementation of. There’s a [separate section on
patterns][patterns] that covers all the patterns that are possible here.
[patterns]: patterns.html
-So what’s the big advantage? Well, there are a few. First of all, `match`
-enforces ‘exhaustiveness checking’. Do you see that last arm, the one with the
-underscore (`_`)? If we remove that arm, Rust will give us an error:
+One of the many advantages of `match` is it enforces ‘exhaustiveness checking’.
+For example if we remove the last arm with the underscore `_`, the compiler will
+give us an error:
```text
error: non-exhaustive patterns: `_` not covered
```
-In other words, Rust is trying to tell us we forgot a value. Because `x` is an
-integer, Rust knows that it can have a number of different values – for
-example, `6`. Without the `_`, however, there is no arm that could match, and
-so Rust refuses to compile the code. `_` acts like a ‘catch-all arm’. If none
-of the other arms match, the arm with `_` will, and since we have this
-catch-all arm, we now have an arm for every possible value of `x`, and so our
-program will compile successfully.
+Rust is telling us that we forgot a value. The compiler infers from `x` that it
+can have any positive 32bit value; for example 1 to 2,147,483,647. The `_` acts
+as a 'catch-all', and will catch all possible values that *aren't* specified in
+an arm of `match`. As you can see with the previous example, we provide `match`
+arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`.
`match` is also an expression, which means we can use it on the right-hand
side of a `let` binding or directly where an expression is used:
};
```
-Sometimes it’s a nice way of converting something from one type to another.
+Sometimes it’s a nice way of converting something from one type to another; in
+this example the integers are converted to `String`.
# Matching on enums
Again, the Rust compiler checks exhaustiveness, so it demands that you
have a match arm for every variant of the enum. If you leave one off, it
-will give you a compile-time error unless you use `_`.
+will give you a compile-time error unless you use `_` or provide all possible
+arms.
Unlike the previous uses of `match`, you can’t use the normal `if`
statement to do this. You can use the [`if let`][if-let] statement,
If it wasn’t, we couldn’t take a mutable borrow to an immutable value.
You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
-this is because `y` is an `&mut` reference. You'll also need to use them for
+this is because `y` is a `&mut` reference. You'll also need to use them for
accessing the contents of a reference as well.
Otherwise, `&mut` references are just like references. There _is_ a large
use core::mem::{align_of_val, size_of_val};
use core::intrinsics::abort;
use core::mem;
+use core::mem::uninitialized;
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
}
}
+impl<T> Weak<T> {
+ /// Constructs a new `Weak<T>` without an accompanying instance of T.
+ ///
+ /// This allocates memory for T, but does not initialize it. Calling
+ /// Weak<T>::upgrade() on the return value always gives None.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(downgraded_weak)]
+ ///
+ /// use std::sync::Weak;
+ ///
+ /// let empty: Weak<i64> = Weak::new();
+ /// ```
+ #[unstable(feature = "downgraded_weak",
+ reason = "recently added",
+ issue = "30425")]
+ pub fn new() -> Weak<T> {
+ unsafe {
+ Weak { _ptr: Shared::new(Box::into_raw(box ArcInner {
+ strong: atomic::AtomicUsize::new(0),
+ weak: atomic::AtomicUsize::new(1),
+ data: uninitialized(),
+ }))}
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use std::clone::Clone;
let foo_arc = Arc::from(foo);
assert!(123 == *foo_arc);
}
+
+ #[test]
+ fn test_new_weak() {
+ let foo: Weak<usize> = Weak::new();
+ assert!(foo.upgrade().is_none());
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
use core::intrinsics::{assume, abort};
use core::marker;
use core::marker::Unsize;
-use core::mem::{self, align_of_val, size_of_val, forget};
+use core::mem::{self, align_of_val, size_of_val, forget, uninitialized};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
}
}
+impl<T> Weak<T> {
+ /// Constructs a new `Weak<T>` without an accompanying instance of T.
+ ///
+ /// This allocates memory for T, but does not initialize it. Calling
+ /// Weak<T>::upgrade() on the return value always gives None.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(downgraded_weak)]
+ ///
+ /// use std::rc::Weak;
+ ///
+ /// let empty: Weak<i64> = Weak::new();
+ /// ```
+ #[unstable(feature = "downgraded_weak",
+ reason = "recently added",
+ issue="30425")]
+ pub fn new() -> Weak<T> {
+ unsafe {
+ Weak {
+ _ptr: Shared::new(Box::into_raw(box RcBox {
+ strong: Cell::new(0),
+ weak: Cell::new(1),
+ value: uninitialized(),
+ })),
+ }
+ }
+ }
+}
+
// NOTE: We checked_add here to deal with mem::forget safety. In particular
// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
// you can free the allocation while outstanding Rcs (or Weaks) exist.
let foo_rc = Rc::from(foo);
assert!(123 == *foo_rc);
}
+
+ #[test]
+ fn test_new_weak() {
+ let foo: Weak<usize> = Weak::new();
+ assert!(foo.upgrade().is_none());
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
Take{iter: self, n: n}
}
- /// An iterator similar to `fold()`, with internal state.
- ///
- /// `scan()` accumulates a final value, similar to [`fold()`], but instead
- /// of passing along an accumulator, it maintains the accumulator internally.
+ /// An iterator adaptor similar to [`fold()`] that holds internal state and
+ /// produces a new iterator.
///
/// [`fold()`]: #method.fold
///
- /// On each iteraton of `scan()`, you can assign to the internal state, and
- /// a mutable reference to the state is passed as the first argument to the
- /// closure, allowing you to modify it on each iteration.
+ /// `scan()` takes two arguments: an initial value which seeds the internal
+ /// state, and a closure with two arguments, the first being a mutable
+ /// reference to the internal state and the second an iterator element.
+ /// The closure can assign to the internal state to share state between
+ /// iterations.
+ ///
+ /// On iteration, the closure will be applied to each element of the
+ /// iterator and the return value from the closure, an [`Option`], is
+ /// yielded by the iterator.
+ ///
+ /// [`Option`]: ../option/enum.Option.html
///
/// # Examples
///
use syntax::ast_util::{self, IdVisitingOperation};
use syntax::attr::{self, AttrMetaMethods};
use syntax::codemap::Span;
+use syntax::errors::{self, DiagnosticBuilder};
use syntax::parse::token::InternedString;
use syntax::ast;
use syntax::attr::ThinAttributesExt;
use rustc_front::util;
use rustc_front::intravisit as hir_visit;
use syntax::visit as ast_visit;
-use syntax::errors;
/// Information about the registered lints.
///
/// in trans that run after the main lint pass is finished. Most
/// lints elsewhere in the compiler should call
/// `Session::add_lint()` instead.
-pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
- lvlsrc: LevelSource, span: Option<Span>, msg: &str) {
+pub fn raw_emit_lint(sess: &Session,
+ lint: &'static Lint,
+ lvlsrc: LevelSource,
+ span: Option<Span>,
+ msg: &str) {
+ raw_struct_lint(sess, lint, lvlsrc, span, msg).emit();
+}
+
+pub fn raw_struct_lint<'a>(sess: &'a Session,
+ lint: &'static Lint,
+ lvlsrc: LevelSource,
+ span: Option<Span>,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
let (mut level, source) = lvlsrc;
- if level == Allow { return }
+ if level == Allow {
+ return sess.diagnostic().struct_dummy();
+ }
let name = lint.name_lower();
let mut def = None;
// For purposes of printing, we can treat forbid as deny.
if level == Forbid { level = Deny; }
- match (level, span) {
- (Warn, Some(sp)) => sess.span_warn(sp, &msg[..]),
- (Warn, None) => sess.warn(&msg[..]),
- (Deny, Some(sp)) => sess.span_err(sp, &msg[..]),
- (Deny, None) => sess.err(&msg[..]),
+ let mut err = match (level, span) {
+ (Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]),
+ (Warn, None) => sess.struct_warn(&msg[..]),
+ (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
+ (Deny, None) => sess.struct_err(&msg[..]),
_ => sess.bug("impossible level in raw_emit_lint"),
- }
+ };
if let Some(span) = def {
- sess.span_note(span, "lint level defined here");
+ err.span_note(span, "lint level defined here");
}
+
+ err
}
pub trait LintContext: Sized {
self.lints().levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl)
}
- fn lookup_and_emit(&self, lint: &'static Lint, span: Option<Span>, msg: &str) {
- let (level, src) = match self.lints().levels.get(&LintId::of(lint)) {
- None => return,
- Some(&(Warn, src)) => {
+ fn level_src(&self, lint: &'static Lint) -> Option<LevelSource> {
+ self.lints().levels.get(&LintId::of(lint)).map(|ls| match ls {
+ &(Warn, src) => {
let lint_id = LintId::of(builtin::WARNINGS);
(self.lints().get_level_source(lint_id).0, src)
}
- Some(&pair) => pair,
+ _ => *ls
+ })
+ }
+
+ fn lookup_and_emit(&self, lint: &'static Lint, span: Option<Span>, msg: &str) {
+ let (level, src) = match self.level_src(lint) {
+ None => return,
+ Some(pair) => pair,
};
raw_emit_lint(&self.sess(), lint, (level, src), span, msg);
}
+ fn lookup(&self,
+ lint: &'static Lint,
+ span: Option<Span>,
+ msg: &str)
+ -> DiagnosticBuilder {
+ let (level, src) = match self.level_src(lint) {
+ None => return self.sess().diagnostic().struct_dummy(),
+ Some(pair) => pair,
+ };
+
+ raw_struct_lint(&self.sess(), lint, (level, src), span, msg)
+ }
+
/// Emit a lint at the appropriate level, for a particular span.
fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) {
self.lookup_and_emit(lint, Some(span), msg);
}
+ fn struct_span_lint(&self,
+ lint: &'static Lint,
+ span: Span,
+ msg: &str)
+ -> DiagnosticBuilder {
+ self.lookup(lint, Some(span), msg)
+ }
+
/// Emit a lint and note at the appropriate level, for a particular span.
fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
note_span: Span, note: &str) {
- self.span_lint(lint, span, msg);
+ let mut err = self.lookup(lint, Some(span), msg);
if self.current_level(lint) != Level::Allow {
if note_span == span {
- self.sess().fileline_note(note_span, note)
+ err.fileline_note(note_span, note);
} else {
- self.sess().span_note(note_span, note)
+ err.span_note(note_span, note);
}
}
+ err.emit();
}
/// Emit a lint and help at the appropriate level, for a particular span.
fn span_lint_help(&self, lint: &'static Lint, span: Span,
msg: &str, help: &str) {
+ let mut err = self.lookup(lint, Some(span), msg);
self.span_lint(lint, span, msg);
if self.current_level(lint) != Level::Allow {
- self.sess().span_help(span, help)
+ err.span_help(span, help);
}
+ err.emit();
}
/// Emit a lint at the appropriate level, with no associated span.
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
- GatherNodeLevels};
+ raw_struct_lint, GatherNodeLevels};
/// Specification of a single lint.
#[derive(Copy, Clone, Debug)]
// this doesn't come from a macro that has #[allow_internal_unstable]
!self.tcx.sess.codemap().span_allows_unstable(expr.span)
{
- self.tcx.sess.span_err(
+ let mut err = self.tcx.sess.struct_span_err(
expr.span,
"const fns are an unstable feature");
fileline_help!(
- self.tcx.sess,
+ &mut err,
expr.span,
"in Nightly builds, add `#![feature(const_fn)]` to the crate \
attributes to enable");
+ err.emit();
}
let qualif = self.fn_like(fn_like.kind(),
if !is_const {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
- fn span_limited_call_error(tcx: &ty::ctxt, span: Span, s: &str) {
- span_err!(tcx.sess, span, E0015, "{}", s);
- }
-
// FIXME(#24111) Remove this check when const fn stabilizes
- if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
- span_limited_call_error(&v.tcx, e.span,
- &format!("function calls in {}s are limited to \
- struct and enum constructors",
- v.msg()));
- v.tcx.sess.span_note(e.span,
- "a limited form of compile-time function \
- evaluation is available on a nightly \
- compiler via `const fn`");
+ let (msg, note) =
+ if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
+ (format!("function calls in {}s are limited to \
+ struct and enum constructors",
+ v.msg()),
+ Some("a limited form of compile-time function \
+ evaluation is available on a nightly \
+ compiler via `const fn`"))
} else {
- span_limited_call_error(&v.tcx, e.span,
- &format!("function calls in {}s are limited \
- to constant functions, \
- struct and enum constructors",
- v.msg()));
+ (format!("function calls in {}s are limited \
+ to constant functions, \
+ struct and enum constructors",
+ v.msg()),
+ None)
+ };
+ let mut err = struct_span_err!(v.tcx.sess, e.span, E0015, "{}", msg);
+ if let Some(note) = note {
+ err.span_note(e.span, note);
}
+ err.emit();
}
}
}
if inlined_arms.is_empty() {
if !pat_ty.is_empty(cx.tcx) {
// We know the type is inhabited, so this must be wrong
- span_err!(cx.tcx.sess, ex.span, E0002,
- "non-exhaustive patterns: type {} is non-empty",
- pat_ty);
- span_help!(cx.tcx.sess, ex.span,
+ let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002,
+ "non-exhaustive patterns: type {} is non-empty",
+ pat_ty);
+ span_help!(&mut err, ex.span,
"Please ensure that all possible cases are being handled; \
possibly adding wildcards or more match arms.");
+ err.emit();
}
// If the type *is* empty, it's vacuously exhaustive
return;
&& variant.kind() == VariantKind::Unit
) {
let ty_path = cx.tcx.item_path_str(edef.did);
- span_warn!(cx.tcx.sess, p.span, E0170,
+ let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
"pattern binding `{}` is named the same as one \
of the variants of the type `{}`",
ident.node, ty_path);
- fileline_help!(cx.tcx.sess, p.span,
+ fileline_help!(err, p.span,
"if you meant to match on a variant, \
consider making the path in the pattern qualified: `{}::{}`",
ty_path, ident.node);
+ err.emit();
}
}
}
Ok(_) => {}
Err(err) => {
- span_err!(cx.tcx.sess, err.span, E0471,
- "constant evaluation error: {}",
- err.description());
+ let mut diag = struct_span_err!(cx.tcx.sess, err.span, E0471,
+ "constant evaluation error: {}",
+ err.description());
if !p.span.contains(err.span) {
- cx.tcx.sess.span_note(p.span,
- "in pattern here")
+ diag.span_note(p.span, "in pattern here");
}
+ diag.emit();
}
}
}
} else if has_guard {
span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
} else if by_ref_span.is_some() {
- span_err!(cx.tcx.sess, p.span, E0009,
- "cannot bind by-move and by-ref in the same pattern");
- span_note!(cx.tcx.sess, by_ref_span.unwrap(), "by-ref binding occurs here");
+ let mut err = struct_span_err!(cx.tcx.sess, p.span, E0009,
+ "cannot bind by-move and by-ref in the same pattern");
+ span_note!(&mut err, by_ref_span.unwrap(), "by-ref binding occurs here");
+ err.emit();
}
};
// This error is probably a little obscure, but I imagine that it
// can be refined over time.
if link2 != link || link == RequireStatic {
- sess.err(&format!("cannot satisfy dependencies so `{}` only \
- shows up once", sess.cstore.crate_name(cnum)));
- sess.help("having upstream crates all available in one format \
- will likely make this go away");
+ sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \
+ shows up once", sess.cstore.crate_name(cnum)))
+ .help("having upstream crates all available in one format \
+ will likely make this go away")
+ .emit();
}
}
None => { m.insert(cnum, link); }
this.session.entry_type.set(Some(config::EntryMain));
} else {
// No main function
- this.session.err("main function not found");
+ let mut err = this.session.struct_err("main function not found");
if !this.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
- this.session.note("the main function must be defined at the crate level \
- but you have one or more functions named 'main' that are not \
- defined at the crate level. Either move the definition or \
- attach the `#[main]` attribute to override this behavior.");
+ err.note("the main function must be defined at the crate level \
+ but you have one or more functions named 'main' that are not \
+ defined at the crate level. Either move the definition or \
+ attach the `#[main]` attribute to override this behavior.");
for &(_, span) in &this.non_main_fns {
- this.session.span_note(span, "here is a function named 'main'");
+ err.span_note(span, "here is a function named 'main'");
}
+ err.emit();
this.session.abort_if_errors();
+ } else {
+ err.emit();
}
}
}
use std::char::from_u32;
use std::fmt;
use syntax::ast;
+use syntax::errors::DiagnosticBuilder;
use syntax::codemap::{self, Pos, Span};
use syntax::parse::token;
use syntax::ptr::P;
impl<'tcx> ty::ctxt<'tcx> {
pub fn note_and_explain_region(&self,
+ err: &mut DiagnosticBuilder,
prefix: &str,
region: ty::Region,
suffix: &str) {
};
let span = match scope.span(&self.region_maps, &self.map) {
Some(s) => s,
- None => return self.sess.note(&unknown_scope())
+ None => {
+ err.note(&unknown_scope());
+ return;
+ }
};
let tag = match self.map.find(scope.node_id(&self.region_maps)) {
Some(ast_map::NodeBlock(_)) => "block",
Some(ast_map::NodeStmt(_)) => "statement",
Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
Some(_) | None => {
- return self.sess.span_note(span, &unknown_scope());
+ err.span_note(span, &unknown_scope());
+ return;
}
};
let scope_decorated_tag = match self.region_maps.code_extent_data(scope) {
};
let message = format!("{}{}{}", prefix, description, suffix);
if let Some(span) = span {
- self.sess.span_note(span, &message);
+ err.span_note(span, &message);
} else {
- self.sess.note(&message);
+ err.note(&message);
}
}
}
fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
-> Vec<RegionResolutionError<'tcx>>;
- fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>);
+ fn report_type_error(&self,
+ trace: TypeTrace<'tcx>,
+ terr: &TypeError<'tcx>)
+ -> DiagnosticBuilder<'tcx>;
- fn check_and_note_conflicting_crates(&self, terr: &TypeError<'tcx>, sp: Span);
+ fn check_and_note_conflicting_crates(&self,
+ err: &mut DiagnosticBuilder,
+ terr: &TypeError<'tcx>,
+ sp: Span);
fn report_and_explain_type_error(&self,
trace: TypeTrace<'tcx>,
trace_origin: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
same_regions: &[SameRegions]);
- fn give_suggestion(&self, same_regions: &[SameRegions]);
+ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegions]);
}
trait ErrorReportingHelpers<'tcx> {
fn report_inference_failure(&self,
- var_origin: RegionVariableOrigin);
+ var_origin: RegionVariableOrigin)
+ -> DiagnosticBuilder<'tcx>;
fn note_region_origin(&self,
+ err: &mut DiagnosticBuilder,
origin: &SubregionOrigin<'tcx>);
fn give_expl_lifetime_param(&self,
+ err: &mut DiagnosticBuilder,
decl: &hir::FnDecl,
unsafety: hir::Unsafety,
constness: hir::Constness,
}
}
- fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>) {
+ fn report_type_error(&self,
+ trace: TypeTrace<'tcx>,
+ terr: &TypeError<'tcx>)
+ -> DiagnosticBuilder<'tcx> {
let expected_found_str = match self.values_str(&trace.values) {
Some(v) => v,
None => {
- return; /* derived error */
+ return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
}
};
- span_err!(self.tcx.sess, trace.origin.span(), E0308,
- "{}: {} ({})",
- trace.origin,
- expected_found_str,
- terr);
+ let mut err = struct_span_err!(self.tcx.sess,
+ trace.origin.span(),
+ E0308,
+ "{}: {} ({})",
+ trace.origin,
+ expected_found_str,
+ terr);
- self.check_and_note_conflicting_crates(terr, trace.origin.span());
+ self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
match trace.origin {
TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
- hir::MatchSource::IfLetDesugar{..} =>
- self.tcx.sess.span_note(arm_span, "`if let` arm with an incompatible type"),
- _ => self.tcx.sess.span_note(arm_span, "match arm with an incompatible type"),
+ hir::MatchSource::IfLetDesugar{..} => {
+ err.span_note(arm_span, "`if let` arm with an incompatible type");
+ }
+ _ => {
+ err.span_note(arm_span, "match arm with an incompatible type");
+ }
},
_ => ()
}
+ err
}
/// Adds a note if the types come from similarly named crates
- fn check_and_note_conflicting_crates(&self, terr: &TypeError<'tcx>, sp: Span) {
- let report_path_match = |did1: DefId, did2: DefId| {
+ fn check_and_note_conflicting_crates(&self,
+ err: &mut DiagnosticBuilder,
+ terr: &TypeError<'tcx>,
+ sp: Span) {
+ let report_path_match = |err: &mut DiagnosticBuilder, did1: DefId, did2: DefId| {
// Only external crates, if either is from a local
// module we could have false positives
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
// for imported and non-imported crates
if exp_path == found_path {
let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);
- self.tcx.sess.span_note(sp, &format!("Perhaps two different versions \
- of crate `{}` are being used?",
- crate_name));
+ err.span_note(sp, &format!("Perhaps two different versions \
+ of crate `{}` are being used?",
+ crate_name));
}
}
};
(&ty::TyStruct(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
(&ty::TyEnum(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
(&ty::TyStruct(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) => {
- report_path_match(exp_adt.did, found_adt.did);
+ report_path_match(err, exp_adt.did, found_adt.did);
},
_ => ()
}
},
TypeError::Traits(ref exp_found) => {
- report_path_match(exp_found.expected, exp_found.found);
+ report_path_match(err, exp_found.expected, exp_found.found);
},
_ => () // FIXME(#22750) handle traits and stuff
}
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>) {
let span = trace.origin.span();
- self.report_type_error(trace, terr);
- self.tcx.note_and_explain_type_err(terr, span);
+ let mut err = self.report_type_error(trace, terr);
+ self.tcx.note_and_explain_type_err(&mut err, terr, span);
+ err.emit();
}
/// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
format!("the associated type `{}`", p),
};
- match sub {
+ let mut err = match sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
- span_err!(
- self.tcx.sess, origin.span(), E0309,
- "{} may not live long enough", labeled_user_string);
- self.tcx.sess.fileline_help(
- origin.span(),
- &format!(
- "consider adding an explicit lifetime bound `{}: {}`...",
- bound_kind,
- sub));
+ let mut err = struct_span_err!(self.tcx.sess,
+ origin.span(),
+ E0309,
+ "{} may not live long enough",
+ labeled_user_string);
+ err.fileline_help(origin.span(),
+ &format!("consider adding an explicit lifetime bound `{}: {}`...",
+ bound_kind,
+ sub));
+ err
}
ty::ReStatic => {
// Does the required lifetime have a nice name we can print?
- span_err!(
- self.tcx.sess, origin.span(), E0310,
- "{} may not live long enough", labeled_user_string);
- self.tcx.sess.fileline_help(
- origin.span(),
- &format!(
- "consider adding an explicit lifetime bound `{}: 'static`...",
- bound_kind));
+ let mut err = struct_span_err!(self.tcx.sess,
+ origin.span(),
+ E0310,
+ "{} may not live long enough",
+ labeled_user_string);
+ err.fileline_help(origin.span(),
+ &format!("consider adding an explicit lifetime \
+ bound `{}: 'static`...",
+ bound_kind));
+ err
}
_ => {
// If not, be less specific.
- span_err!(
- self.tcx.sess, origin.span(), E0311,
- "{} may not live long enough",
- labeled_user_string);
- self.tcx.sess.fileline_help(
- origin.span(),
- &format!(
- "consider adding an explicit lifetime bound for `{}`",
- bound_kind));
+ let mut err = struct_span_err!(self.tcx.sess,
+ origin.span(),
+ E0311,
+ "{} may not live long enough",
+ labeled_user_string);
+ err.fileline_help(origin.span(),
+ &format!("consider adding an explicit lifetime bound for `{}`",
+ bound_kind));
self.tcx.note_and_explain_region(
+ &mut err,
&format!("{} must be valid for ", labeled_user_string),
sub,
"...");
+ err
}
- }
+ };
- self.note_region_origin(&origin);
+ self.note_region_origin(&mut err, &origin);
+ err.emit();
}
fn report_concrete_failure(&self,
self.report_and_explain_type_error(trace, &terr);
}
infer::Reborrow(span) => {
- span_err!(self.tcx.sess, span, E0312,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0312,
"lifetime of reference outlines \
lifetime of borrowed content...");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"...the reference is valid for ",
sub,
"...");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"...but the borrowed content is only valid for ",
sup,
"");
+ err.emit();
}
infer::ReborrowUpvar(span, ref upvar_id) => {
- span_err!(self.tcx.sess, span, E0313,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0313,
"lifetime of borrowed pointer outlives \
lifetime of captured variable `{}`...",
self.tcx.local_var_name_str(upvar_id.var_id));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"...the borrowed pointer is valid for ",
sub,
"...");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
&format!("...but `{}` is only valid for ",
self.tcx.local_var_name_str(upvar_id.var_id)),
sup,
"");
+ err.emit();
}
infer::InfStackClosure(span) => {
- span_err!(self.tcx.sess, span, E0314,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0314,
"closure outlives stack frame");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"...the closure must be valid for ",
sub,
"...");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"...but the closure's stack frame is only valid for ",
sup,
"");
+ err.emit();
}
infer::InvokeClosure(span) => {
- span_err!(self.tcx.sess, span, E0315,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0315,
"cannot invoke closure outside of its lifetime");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the closure is only valid for ",
sup,
"");
+ err.emit();
}
infer::DerefPointer(span) => {
- span_err!(self.tcx.sess, span, E0473,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0473,
"dereference of reference outside its lifetime");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the reference is only valid for ",
sup,
"");
+ err.emit();
}
infer::FreeVariable(span, id) => {
- span_err!(self.tcx.sess, span, E0474,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0474,
"captured variable `{}` does not outlive the enclosing closure",
self.tcx.local_var_name_str(id));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"captured variable is valid for ",
sup,
"");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"closure is valid for ",
sub,
"");
+ err.emit();
}
infer::IndexSlice(span) => {
- span_err!(self.tcx.sess, span, E0475,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0475,
"index of slice outside its lifetime");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the slice is only valid for ",
sup,
"");
+ err.emit();
}
infer::RelateObjectBound(span) => {
- span_err!(self.tcx.sess, span, E0476,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0476,
"lifetime of the source pointer does not outlive \
lifetime bound of the object type");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"object type is valid for ",
sub,
"");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"source pointer is only valid for ",
sup,
"");
+ err.emit();
}
infer::RelateParamBound(span, ty) => {
- span_err!(self.tcx.sess, span, E0477,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0477,
"the type `{}` does not fulfill the required lifetime",
self.ty_to_string(ty));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"type must outlive ",
sub,
"");
+ err.emit();
}
infer::RelateRegionParamBound(span) => {
- span_err!(self.tcx.sess, span, E0478,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0478,
"lifetime bound not satisfied");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"lifetime parameter instantiated with ",
sup,
"");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"but lifetime parameter must outlive ",
sub,
"");
+ err.emit();
}
infer::RelateDefaultParamBound(span, ty) => {
- span_err!(self.tcx.sess, span, E0479,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0479,
"the type `{}` (provided as the value of \
a type parameter) is not valid at this point",
self.ty_to_string(ty));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"type must outlive ",
sub,
"");
+ err.emit();
}
infer::CallRcvr(span) => {
- span_err!(self.tcx.sess, span, E0480,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0480,
"lifetime of method receiver does not outlive \
the method call");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the receiver is only valid for ",
sup,
"");
+ err.emit();
}
infer::CallArg(span) => {
- span_err!(self.tcx.sess, span, E0481,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0481,
"lifetime of function argument does not outlive \
the function call");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the function argument is only valid for ",
sup,
"");
+ err.emit();
}
infer::CallReturn(span) => {
- span_err!(self.tcx.sess, span, E0482,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0482,
"lifetime of return value does not outlive \
the function call");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the return value is only valid for ",
sup,
"");
+ err.emit();
}
infer::Operand(span) => {
- span_err!(self.tcx.sess, span, E0483,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0483,
"lifetime of operand does not outlive \
the operation");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the operand is only valid for ",
sup,
"");
+ err.emit();
}
infer::AddrOf(span) => {
- span_err!(self.tcx.sess, span, E0484,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0484,
"reference is not valid at the time of borrow");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the borrow is only valid for ",
sup,
"");
+ err.emit();
}
infer::AutoBorrow(span) => {
- span_err!(self.tcx.sess, span, E0485,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0485,
"automatically reference is not valid \
at the time of borrow");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the automatic borrow is only valid for ",
sup,
"");
+ err.emit();
}
infer::ExprTypeIsNotInScope(t, span) => {
- span_err!(self.tcx.sess, span, E0486,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0486,
"type of expression contains references \
that are not valid during the expression: `{}`",
self.ty_to_string(t));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"type is only valid for ",
sup,
"");
+ err.emit();
}
infer::SafeDestructor(span) => {
- span_err!(self.tcx.sess, span, E0487,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0487,
"unsafe use of destructor: destructor might be called \
while references are dead");
// FIXME (22171): terms "super/subregion" are suboptimal
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"superregion: ",
sup,
"");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"subregion: ",
sub,
"");
+ err.emit();
}
infer::BindingTypeIsNotValidAtDecl(span) => {
- span_err!(self.tcx.sess, span, E0488,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0488,
"lifetime of variable does not enclose its declaration");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the variable is only valid for ",
sup,
"");
+ err.emit();
}
infer::ParameterInScope(_, span) => {
- span_err!(self.tcx.sess, span, E0489,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0489,
"type/lifetime parameter not in scope here");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the parameter is only valid for ",
sub,
"");
+ err.emit();
}
infer::DataBorrowed(ty, span) => {
- span_err!(self.tcx.sess, span, E0490,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0490,
"a value of type `{}` is borrowed for too long",
self.ty_to_string(ty));
- self.tcx.note_and_explain_region("the type is valid for ", sub, "");
- self.tcx.note_and_explain_region("but the borrow lasts for ", sup, "");
+ self.tcx.note_and_explain_region(&mut err, "the type is valid for ", sub, "");
+ self.tcx.note_and_explain_region(&mut err, "but the borrow lasts for ", sup, "");
+ err.emit();
}
infer::ReferenceOutlivesReferent(ty, span) => {
- span_err!(self.tcx.sess, span, E0491,
+ let mut err = struct_span_err!(self.tcx.sess, span, E0491,
"in type `{}`, reference has a longer lifetime \
than the data it references",
self.ty_to_string(ty));
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"the pointer is valid for ",
sub,
"");
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"but the referenced data is only valid for ",
sup,
"");
+ err.emit();
}
}
}
sub_region: Region,
sup_origin: SubregionOrigin<'tcx>,
sup_region: Region) {
- self.report_inference_failure(var_origin);
+ let mut err = self.report_inference_failure(var_origin);
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"first, the lifetime cannot outlive ",
sup_region,
"...");
- self.note_region_origin(&sup_origin);
+ self.note_region_origin(&mut err, &sup_origin);
- self.tcx.note_and_explain_region(
+ self.tcx.note_and_explain_region(&mut err,
"but, the lifetime must be valid for ",
sub_region,
"...");
- self.note_region_origin(&sub_origin);
+ self.note_region_origin(&mut err, &sub_origin);
+ err.emit();
}
fn report_processed_errors(&self,
var_origins: &[RegionVariableOrigin],
trace_origins: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
same_regions: &[SameRegions]) {
- for vo in var_origins {
- self.report_inference_failure(vo.clone());
+ for (i, vo) in var_origins.iter().enumerate() {
+ let mut err = self.report_inference_failure(vo.clone());
+ if i == var_origins.len() - 1 {
+ self.give_suggestion(&mut err, same_regions);
+ }
+ err.emit();
}
- self.give_suggestion(same_regions);
+
for &(ref trace, ref terr) in trace_origins {
self.report_and_explain_type_error(trace.clone(), terr);
}
}
- fn give_suggestion(&self, same_regions: &[SameRegions]) {
+ fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegions]) {
let scope_id = same_regions[0].scope_id;
let parent = self.tcx.map.get_parent(scope_id);
let parent_node = self.tcx.map.find(parent);
let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
generics, same_regions, &life_giver);
let (fn_decl, expl_self, generics) = rebuilder.rebuild();
- self.give_expl_lifetime_param(&fn_decl, unsafety, constness, name,
+ self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name,
expl_self.as_ref(), &generics, span);
}
}
impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
fn give_expl_lifetime_param(&self,
+ err: &mut DiagnosticBuilder,
decl: &hir::FnDecl,
unsafety: hir::Unsafety,
constness: hir::Constness,
opt_explicit_self, generics);
let msg = format!("consider using an explicit lifetime \
parameter as shown: {}", suggested_fn);
- self.tcx.sess.span_help(span, &msg[..]);
+ err.span_help(span, &msg[..]);
}
fn report_inference_failure(&self,
- var_origin: RegionVariableOrigin) {
+ var_origin: RegionVariableOrigin)
+ -> DiagnosticBuilder<'tcx> {
let br_string = |br: ty::BoundRegion| {
let mut s = br.to_string();
if !s.is_empty() {
}
};
- span_err!(self.tcx.sess, var_origin.span(), E0495,
+ struct_span_err!(self.tcx.sess, var_origin.span(), E0495,
"cannot infer an appropriate lifetime{} \
due to conflicting requirements",
- var_description);
+ var_description)
}
- fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
+ fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrigin<'tcx>) {
match *origin {
infer::Subtype(ref trace) => {
let desc = match trace.origin {
match self.values_str(&trace.values) {
Some(values_str) => {
- self.tcx.sess.span_note(
+ err.span_note(
trace.origin.span(),
&format!("...so that {} ({})",
desc, values_str));
// all, since it is derived, but that would
// require more refactoring than I feel like
// doing right now. - nmatsakis
- self.tcx.sess.span_note(
+ err.span_note(
trace.origin.span(),
&format!("...so that {}", desc));
}
}
}
infer::Reborrow(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that reference does not outlive \
borrowed content");
}
infer::ReborrowUpvar(span, ref upvar_id) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!(
"...so that closure can access `{}`",
self.tcx.local_var_name_str(upvar_id.var_id)
- .to_string()))
+ .to_string()));
}
infer::InfStackClosure(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that closure does not outlive its stack frame");
}
infer::InvokeClosure(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that closure is not invoked outside its lifetime");
}
infer::DerefPointer(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that pointer is not dereferenced \
outside its lifetime");
}
infer::FreeVariable(span, id) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so that captured variable `{}` \
does not outlive the enclosing closure",
self.tcx.local_var_name_str(id)));
}
infer::IndexSlice(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that slice is not indexed outside the lifetime");
}
infer::RelateObjectBound(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that it can be closed over into an object");
}
infer::CallRcvr(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that method receiver is valid for the method call");
}
infer::CallArg(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that argument is valid for the call");
}
infer::CallReturn(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that return value is valid for the call");
}
infer::Operand(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that operand is valid for operation");
}
infer::AddrOf(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that reference is valid \
at the time of borrow");
}
infer::AutoBorrow(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that auto-reference is valid \
at the time of borrow");
}
infer::ExprTypeIsNotInScope(t, span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so type `{}` of expression is valid during the \
expression",
self.ty_to_string(t)));
}
infer::BindingTypeIsNotValidAtDecl(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that variable is valid at time of its declaration");
}
infer::ParameterInScope(_, span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that a type/lifetime parameter is in scope here");
}
infer::DataBorrowed(ty, span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so that the type `{}` is not borrowed for too long",
self.ty_to_string(ty)));
}
infer::ReferenceOutlivesReferent(ty, span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so that the reference type `{}` \
does not outlive the data it points at",
self.ty_to_string(ty)));
}
infer::RelateParamBound(span, t) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so that the type `{}` \
will meet its required lifetime bounds",
self.ty_to_string(t)));
}
infer::RelateDefaultParamBound(span, t) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
&format!("...so that type parameter \
instantiated with `{}`, \
self.ty_to_string(t)));
}
infer::RelateRegionParamBound(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that the declared lifetime parameter bounds \
are satisfied");
}
infer::SafeDestructor(span) => {
- self.tcx.sess.span_note(
+ err.span_note(
span,
"...so that references are valid when the destructor \
- runs")
+ runs");
}
}
}
use syntax::ast;
use syntax::codemap;
use syntax::codemap::{Span, DUMMY_SP};
+use syntax::errors::DiagnosticBuilder;
use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
use self::combine::CombineFields;
sp: Span,
mk_msg: M,
actual_ty: String,
- err: Option<&TypeError<'tcx>>) where
- M: FnOnce(Option<String>, String) -> String,
+ err: Option<&TypeError<'tcx>>)
+ where M: FnOnce(Option<String>, String) -> String,
{
self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
}
+ pub fn type_error_struct_str<M>(&self,
+ sp: Span,
+ mk_msg: M,
+ actual_ty: String,
+ err: Option<&TypeError<'tcx>>)
+ -> DiagnosticBuilder<'tcx>
+ where M: FnOnce(Option<String>, String) -> String,
+ {
+ self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
+ }
+
pub fn type_error_message_str_with_expected<M>(&self,
sp: Span,
mk_msg: M,
expected_ty: Option<Ty<'tcx>>,
actual_ty: String,
- err: Option<&TypeError<'tcx>>) where
- M: FnOnce(Option<String>, String) -> String,
+ err: Option<&TypeError<'tcx>>)
+ where M: FnOnce(Option<String>, String) -> String,
+ {
+ self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
+ .emit();
+ }
+
+ pub fn type_error_struct_str_with_expected<M>(&self,
+ sp: Span,
+ mk_msg: M,
+ expected_ty: Option<Ty<'tcx>>,
+ actual_ty: String,
+ err: Option<&TypeError<'tcx>>)
+ -> DiagnosticBuilder<'tcx>
+ where M: FnOnce(Option<String>, String) -> String,
{
debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
format!(" ({})", t_err)
});
- self.tcx.sess.span_err(sp, &format!("{}{}",
+ let mut db = self.tcx.sess.struct_span_err(sp, &format!("{}{}",
mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
error_str));
if let Some(err) = err {
- self.tcx.note_and_explain_type_err(err, sp)
+ self.tcx.note_and_explain_type_err(&mut db, err, sp);
}
+ db
+ } else {
+ self.tcx.sess.diagnostic().struct_dummy()
}
}
sp: Span,
mk_msg: M,
actual_ty: Ty<'tcx>,
- err: Option<&TypeError<'tcx>>) where
- M: FnOnce(String) -> String,
+ err: Option<&TypeError<'tcx>>)
+ where M: FnOnce(String) -> String,
+ {
+ self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
+ }
+
+ pub fn type_error_struct<M>(&self,
+ sp: Span,
+ mk_msg: M,
+ actual_ty: Ty<'tcx>,
+ err: Option<&TypeError<'tcx>>)
+ -> DiagnosticBuilder<'tcx>
+ where M: FnOnce(String) -> String,
{
let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
// Don't report an error if actual type is TyError.
if actual_ty.references_error() {
- return;
+ return self.tcx.sess.diagnostic().struct_dummy();
}
- self.type_error_message_str(sp,
+ self.type_error_struct_str(sp,
move |_e, a| { mk_msg(a) },
- self.ty_to_string(actual_ty), err);
+ self.ty_to_string(actual_ty), err)
}
pub fn report_mismatched_types(&self,
},
_ => false
};
- span_err!(self.ir.tcx.sess, sp, E0269, "not all control paths return a value");
+ let mut err = struct_span_err!(self.ir.tcx.sess,
+ sp,
+ E0269,
+ "not all control paths return a value");
if ends_with_stmt {
let last_stmt = body.stmts.first().unwrap();
let original_span = original_sp(self.ir.tcx.sess.codemap(),
hi: original_span.hi,
expn_id: original_span.expn_id
};
- self.ir.tcx.sess.span_help(
- span_semicolon, "consider removing this semicolon:");
+ err.span_help(span_semicolon, "consider removing this semicolon:");
}
+ err.emit();
}
}
ty::FnDiverging
}
}
-fn signal_shadowing_problem(
- sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) {
- if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
+fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) {
+ let mut err = if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
// lifetime/lifetime shadowing is an error
- span_err!(sess, shadower.span, E0496,
- "{} name `{}` shadows a \
- {} name that is already in scope",
- shadower.kind.desc(), name, orig.kind.desc());
+ struct_span_err!(sess, shadower.span, E0496,
+ "{} name `{}` shadows a \
+ {} name that is already in scope",
+ shadower.kind.desc(), name, orig.kind.desc())
} else {
// shadowing involving a label is only a warning, due to issues with
// labels and lifetimes not being macro-hygienic.
- sess.span_warn(shadower.span,
- &format!("{} name `{}` shadows a \
- {} name that is already in scope",
- shadower.kind.desc(), name, orig.kind.desc()));
- }
- sess.span_note(orig.span,
- &format!("shadowed {} `{}` declared here",
- orig.kind.desc(), name));
+ sess.struct_span_warn(shadower.span,
+ &format!("{} name `{}` shadows a \
+ {} name that is already in scope",
+ shadower.kind.desc(), name, orig.kind.desc()))
+ };
+ err.span_note(orig.span,
+ &format!("shadowed {} `{}` declared here",
+ orig.kind.desc(), name));
+ err.emit();
}
// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
// This is an 'unmarked' API, which should not exist
// in the standard library.
if self.tcx.sess.features.borrow().unmarked_api {
- self.tcx.sess.span_warn(span, "use of unmarked library feature");
- self.tcx.sess.span_note(span, "this is either a bug in the library you are \
+ self.tcx.sess.struct_span_warn(span, "use of unmarked library feature")
+ .span_note(span, "this is either a bug in the library you are \
using or a bug in the compiler - please \
- report it in both places");
+ report it in both places")
+ .emit()
} else {
- self.tcx.sess.span_err(span, "use of unmarked library feature");
- self.tcx.sess.span_note(span, "this is either a bug in the library you are \
+ self.tcx.sess.struct_span_err(span, "use of unmarked library feature")
+ .span_note(span, "this is either a bug in the library you are \
using or a bug in the compiler - please \
- report it in both places");
- self.tcx.sess.span_note(span, "use #![feature(unmarked_api)] in the \
- crate attributes to override this");
+ report it in both places")
+ .span_note(span, "use #![feature(unmarked_api)] in the \
+ crate attributes to override this")
+ .emit()
}
}
}
use util::nodemap::{FnvHashMap, FnvHashSet};
use std::fmt;
-use syntax::codemap::Span;
use syntax::attr::{AttributeMethods, AttrMetaMethods};
+use syntax::codemap::Span;
+use syntax::errors::DiagnosticBuilder;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
// then $X will be unified with TyError, but the error still needs to be
// reported.
if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
- span_err!(
- infcx.tcx.sess, obligation.cause.span, E0271,
+ let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate,
error.err);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
{
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
- span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
- "overflow evaluating the requirement `{}`",
- predicate);
+ let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
+ "overflow evaluating the requirement `{}`",
+ predicate);
- suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
+ suggest_new_overflow_limit(infcx.tcx, &mut err, obligation.cause.span);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
infcx.tcx.sess.abort_if_errors();
unreachable!();
}
if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
let trait_ref = trait_predicate.to_poly_trait_ref();
- span_err!(
+ let mut err = struct_span_err!(
infcx.tcx.sess, obligation.cause.span, E0277,
"the trait `{}` is not implemented for the type `{}`",
trait_ref, trait_ref.self_ty());
let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
obligation.cause.span);
if let Some(s) = custom_note {
- infcx.tcx.sess.fileline_note(obligation.cause.span, &s);
+ err.fileline_note(obligation.cause.span, &s);
}
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.equality_predicate(obligation.cause.span,
&predicate).err().unwrap();
- span_err!(
+ let mut err = struct_span_err!(
infcx.tcx.sess, obligation.cause.span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.region_outlives_predicate(obligation.cause.span,
&predicate).err().unwrap();
- span_err!(
+ let mut err = struct_span_err!(
infcx.tcx.sess, obligation.cause.span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
- span_err!(
+ let mut err = struct_span_err!(
infcx.tcx.sess, obligation.cause.span, E0280,
"the requirement `{}` is not satisfied",
predicate);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = object_safety_violations(
infcx.tcx, trait_def_id);
- report_object_safety_error(infcx.tcx,
- obligation.cause.span,
- trait_def_id,
- violations);
- note_obligation_cause(infcx, obligation);
+ let mut err = report_object_safety_error(infcx.tcx,
+ obligation.cause.span,
+ trait_def_id,
+ violations);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
ty::Predicate::WellFormed(ty) => {
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
if !actual_trait_ref.self_ty().references_error() {
- span_err!(
+ let mut err = struct_span_err!(
infcx.tcx.sess, obligation.cause.span, E0281,
"type mismatch: the type `{}` implements the trait `{}`, \
but the trait `{}` is required ({})",
expected_trait_ref,
actual_trait_ref,
e);
- note_obligation_cause(infcx, obligation);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
TraitNotObjectSafe(did) => {
let violations = object_safety_violations(infcx.tcx, did);
- report_object_safety_error(infcx.tcx, obligation.cause.span, did, violations);
- note_obligation_cause(infcx, obligation);
+ let mut err = report_object_safety_error(infcx.tcx, obligation.cause.span, did,
+ violations);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
}
span: Span,
trait_def_id: DefId,
violations: Vec<ObjectSafetyViolation>)
+ -> DiagnosticBuilder<'tcx>
{
- span_err!(
+ let mut err = struct_span_err!(
tcx.sess, span, E0038,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));
}
match violation {
ObjectSafetyViolation::SizedSelf => {
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
"the trait cannot require that `Self : Sized`");
}
ObjectSafetyViolation::SupertraitSelf => {
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
"the trait cannot use `Self` as a type parameter \
in the supertrait listing");
ObjectSafetyViolation::Method(method,
MethodViolationCode::StaticMethod) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
&format!("method `{}` has no receiver",
method.name));
ObjectSafetyViolation::Method(method,
MethodViolationCode::ReferencesSelf) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
&format!("method `{}` references the `Self` type \
in its arguments or return type",
ObjectSafetyViolation::Method(method,
MethodViolationCode::Generic) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
&format!("method `{}` has generic type parameters",
method.name));
}
}
}
+ err
}
pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
{
need_type_info(infcx, obligation.cause.span, self_ty);
} else {
- span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
- "type annotations required: cannot resolve `{}`",
- predicate);
- note_obligation_cause(infcx, obligation);
+ let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
+ "type annotations required: \
+ cannot resolve `{}`",
+ predicate);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
}
_ => {
if !infcx.tcx.sess.has_errors() {
- span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
- "type annotations required: cannot resolve `{}`",
- predicate);
- note_obligation_cause(infcx, obligation);
+ let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
+ "type annotations required: cannot resolve `{}`",
+ predicate);
+ note_obligation_cause(infcx, &mut err, obligation);
+ err.emit();
}
}
}
}
fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+ err: &mut DiagnosticBuilder,
obligation: &Obligation<'tcx, T>)
where T: fmt::Display
{
note_obligation_cause_code(infcx,
+ err,
&obligation.predicate,
obligation.cause.span,
&obligation.cause.code);
}
fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+ err: &mut DiagnosticBuilder,
predicate: &T,
cause_span: Span,
cause_code: &ObligationCauseCode<'tcx>)
match *cause_code {
ObligationCauseCode::MiscObligation => { }
ObligationCauseCode::SliceOrArrayElem => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"slice and array elements must have `Sized` type");
}
ObligationCauseCode::ProjectionWf(data) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("required so that the projection `{}` is well-formed",
data));
}
ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("required so that reference `{}` does not outlive its referent",
ref_ty));
}
ObligationCauseCode::ItemObligation(item_def_id) => {
let item_name = tcx.item_path_str(item_def_id);
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("required by `{}`", item_name));
}
ObligationCauseCode::ObjectCastObligation(object_ty) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!(
"required for the cast to the object type `{}`",
infcx.ty_to_string(object_ty)));
}
ObligationCauseCode::RepeatVec => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"the `Copy` trait is required because the \
repeated element will be copied");
}
ObligationCauseCode::VariableType(_) => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"all local variables must have a statically known size");
}
ObligationCauseCode::ReturnType => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"the return type of a function must have a \
statically known size");
}
ObligationCauseCode::AssignmentLhsSized => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"the left-hand-side of an assignment must have a statically known size");
}
ObligationCauseCode::StructInitializerSized => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"structs must have a statically known size to be initialized");
}
let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
let trait_name = tcx.item_path_str(def_id);
let name = tcx.local_var_name_str(var_id);
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("the closure that captures `{}` requires that all captured variables \
implement the trait `{}`",
trait_name));
}
ObligationCauseCode::FieldSized => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"only the last field of a struct or enum variant \
may have a dynamically sized type");
}
ObligationCauseCode::SharedStatic => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
"shared static variables must have a type that implements `Sync`");
}
ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("required because it appears within the type `{}`",
parent_trait_ref.0.self_ty()));
let parent_predicate = parent_trait_ref.to_predicate();
- note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
+ note_obligation_cause_code(infcx,
+ err,
+ &parent_predicate,
+ cause_span,
+ &*data.parent_code);
}
ObligationCauseCode::ImplDerivedObligation(ref data) => {
let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref,
parent_trait_ref.0.self_ty()));
let parent_predicate = parent_trait_ref.to_predicate();
- note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
+ note_obligation_cause_code(infcx,
+ err,
+ &parent_predicate,
+ cause_span,
+ &*data.parent_code);
}
ObligationCauseCode::CompareImplMethodObligation => {
- tcx.sess.fileline_note(
+ err.fileline_note(
cause_span,
&format!("the requirement `{}` appears on the impl method \
but not on the corresponding trait method",
}
}
-fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
+fn suggest_new_overflow_limit(tcx: &ty::ctxt, err:&mut DiagnosticBuilder, span: Span) {
let current_limit = tcx.sess.recursion_limit.get();
let suggested_limit = current_limit * 2;
- tcx.sess.fileline_note(
+ err.fileline_note(
span,
&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
// autorefs) to `&self`. For now, we only accept `self`, `&self`
// and `Box<Self>`.
match method.explicit_self {
- ty::StaticExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::Static => {
return Some(MethodViolationCode::StaticMethod);
}
- ty::ByValueExplicitSelfCategory |
- ty::ByReferenceExplicitSelfCategory(..) |
- ty::ByBoxExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::ByValue |
+ ty::ExplicitSelfCategory::ByReference(..) |
+ ty::ExplicitSelfCategory::ByBox => {
}
}
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::codemap::Span;
+use syntax::errors::DiagnosticBuilder;
use rustc_front::hir;
}
impl<'tcx> ty::ctxt<'tcx> {
- pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
+ pub fn note_and_explain_type_err(&self,
+ db: &mut DiagnosticBuilder,
+ err: &TypeError<'tcx>,
+ sp: Span) {
use self::TypeError::*;
match err.clone() {
RegionsDoesNotOutlive(subregion, superregion) => {
- self.note_and_explain_region("", subregion, "...");
- self.note_and_explain_region("...does not necessarily outlive ",
+ self.note_and_explain_region(db, "", subregion, "...");
+ self.note_and_explain_region(db, "...does not necessarily outlive ",
superregion, "");
}
RegionsNotSame(region1, region2) => {
- self.note_and_explain_region("", region1, "...");
- self.note_and_explain_region("...is not the same lifetime as ",
+ self.note_and_explain_region(db, "", region1, "...");
+ self.note_and_explain_region(db, "...is not the same lifetime as ",
region2, "");
}
RegionsNoOverlap(region1, region2) => {
- self.note_and_explain_region("", region1, "...");
- self.note_and_explain_region("...does not overlap ",
+ self.note_and_explain_region(db, "", region1, "...");
+ self.note_and_explain_region(db, "...does not overlap ",
region2, "");
}
RegionsInsufficientlyPolymorphic(_, conc_region) => {
- self.note_and_explain_region("concrete lifetime that was found is ",
+ self.note_and_explain_region(db, "concrete lifetime that was found is ",
conc_region, "");
}
RegionsOverlyPolymorphic(_, ty::ReVar(_)) => {
// inference variables, it's not very illuminating.
}
RegionsOverlyPolymorphic(_, conc_region) => {
- self.note_and_explain_region("expected concrete lifetime is ",
+ self.note_and_explain_region(db, "expected concrete lifetime is ",
conc_region, "");
}
Sorts(values) => {
let expected_str = values.expected.sort_string(self);
let found_str = values.found.sort_string(self);
if expected_str == found_str && expected_str == "closure" {
- self.sess.span_note(sp,
+ db.span_note(sp,
"no two closures, even if identical, have the same type");
- self.sess.span_help(sp,
+ db.span_help(sp,
"consider boxing your closure and/or using it as a trait object");
}
},
TyParamDefaultMismatch(values) => {
let expected = values.expected;
let found = values.found;
- self.sess.span_note(sp,
- &format!("conflicting type parameter defaults `{}` and `{}`",
- expected.ty,
- found.ty));
+ db.span_note(sp, &format!("conflicting type parameter defaults `{}` and `{}`",
+ expected.ty,
+ found.ty));
match
self.map.as_local_node_id(expected.def_id)
.and_then(|node_id| self.map.opt_span(node_id))
{
Some(span) => {
- self.sess.span_note(span, "a default was defined here...");
+ db.span_note(span, "a default was defined here...");
}
None => {
- self.sess.note(
- &format!("a default is defined on `{}`",
- self.item_path_str(expected.def_id)));
+ db.note(&format!("a default is defined on `{}`",
+ self.item_path_str(expected.def_id)));
}
}
- self.sess.span_note(
+ db.span_note(
expected.origin_span,
"...that was applied to an unconstrained type variable here");
.and_then(|node_id| self.map.opt_span(node_id))
{
Some(span) => {
- self.sess.span_note(span, "a second default was defined here...");
+ db.span_note(span, "a second default was defined here...");
}
None => {
- self.sess.note(
- &format!("a second default is defined on `{}`",
- self.item_path_str(found.def_id)));
+ db.note(&format!("a second default is defined on `{}`",
+ self.item_path_str(found.def_id)));
}
}
- self.sess.span_note(
- found.origin_span,
- "...that also applies to the same type variable here");
+ db.span_note(found.origin_span,
+ "...that also applies to the same type variable here");
}
_ => {}
}
pub use self::ClosureKind::*;
pub use self::Variance::*;
pub use self::DtorKind::*;
-pub use self::ExplicitSelfCategory::*;
pub use self::ImplOrTraitItemContainer::*;
pub use self::BorrowKind::*;
pub use self::ImplOrTraitItem::*;
/// The category of explicit self.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum ExplicitSelfCategory {
- StaticExplicitSelfCategory,
- ByValueExplicitSelfCategory,
- ByReferenceExplicitSelfCategory(Region, hir::Mutability),
- ByBoxExplicitSelfCategory,
+ Static,
+ ByValue,
+ ByReference(Region, hir::Mutability),
+ ByBox,
}
/// A free variable referred to in a function.
use syntax::ast::{NodeId, NodeIdAssigner, Name};
use syntax::codemap::Span;
-use syntax::errors;
+use syntax::errors::{self, DiagnosticBuilder};
use syntax::errors::emitter::{Emitter, BasicEmitter};
use syntax::diagnostics;
use syntax::feature_gate;
}
impl Session {
+ pub fn struct_span_warn<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_span_warn(sp, msg)
+ }
+ pub fn struct_span_warn_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_span_warn_with_code(sp, msg, code)
+ }
+ pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_warn(msg)
+ }
+ pub fn struct_span_err<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ match split_msg_into_multilines(msg) {
+ Some(ref msg) => self.diagnostic().struct_span_err(sp, msg),
+ None => self.diagnostic().struct_span_err(sp, msg),
+ }
+ }
+ pub fn struct_span_err_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ match split_msg_into_multilines(msg) {
+ Some(ref msg) => self.diagnostic().struct_span_err_with_code(sp, msg, code),
+ None => self.diagnostic().struct_span_err_with_code(sp, msg, code),
+ }
+ }
+ pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_err(msg)
+ }
+ pub fn struct_span_fatal<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_span_fatal(sp, msg)
+ }
+ pub fn struct_span_fatal_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
+ }
+ pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ self.diagnostic().struct_fatal(msg)
+ }
+
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
panic!(self.diagnostic().span_fatal(sp, msg))
}
}
pub fn span_err(&self, sp: Span, msg: &str) {
match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err(sp, &msg[..]),
+ Some(msg) => self.diagnostic().span_err(sp, &msg),
None => self.diagnostic().span_err(sp, msg)
}
}
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
+ Some(msg) => self.diagnostic().span_err_with_code(sp, &msg, code),
None => self.diagnostic().span_err_with_code(sp, msg, code)
}
}
None => self.warn(msg),
}
}
- pub fn span_note(&self, sp: Span, msg: &str) {
- self.diagnostic().span_note(sp, msg)
- }
- pub fn span_end_note(&self, sp: Span, msg: &str) {
- self.diagnostic().span_end_note(sp, msg)
- }
-
- /// Prints out a message with a suggested edit of the code.
- ///
- /// See `errors::RenderSpan::Suggestion` for more information.
- pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) {
- self.diagnostic().span_suggestion(sp, msg, suggestion)
- }
- pub fn span_help(&self, sp: Span, msg: &str) {
- self.diagnostic().span_help(sp, msg)
- }
- pub fn fileline_note(&self, sp: Span, msg: &str) {
- self.diagnostic().fileline_note(sp, msg)
- }
- pub fn fileline_help(&self, sp: Span, msg: &str) {
- self.diagnostic().fileline_help(sp, msg)
- }
- pub fn note(&self, msg: &str) {
- self.diagnostic().note(msg)
- }
- pub fn help(&self, msg: &str) {
- self.diagnostic().help(msg)
- }
pub fn opt_span_bug(&self, opt_sp: Option<Span>, msg: &str) -> ! {
match opt_sp {
Some(sp) => self.span_bug(sp, msg),
pub fn bug(&self, msg: &str) -> ! {
self.diagnostic().bug(msg)
}
+ pub fn note_without_error(&self, msg: &str) {
+ self.diagnostic().note_without_error(msg)
+ }
+ pub fn span_note_without_error(&self, sp: Span, msg: &str) {
+ self.diagnostic().span_note_without_error(sp, msg)
+ }
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
self.diagnostic().span_unimpl(sp, msg)
}
impl fmt::Display for ty::ExplicitSelfCategory {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
- ty::StaticExplicitSelfCategory => "static",
- ty::ByValueExplicitSelfCategory => "self",
- ty::ByReferenceExplicitSelfCategory(_, hir::MutMutable) => {
+ ty::ExplicitSelfCategory::Static => "static",
+ ty::ExplicitSelfCategory::ByValue => "self",
+ ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => {
"&mut self"
}
- ty::ByReferenceExplicitSelfCategory(_, hir::MutImmutable) => "&self",
- ty::ByBoxExplicitSelfCategory => "Box<self>",
+ ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self",
+ ty::ExplicitSelfCategory::ByBox => "Box<self>",
})
}
}
format!("`{}`", ol)
};
- match (new_loan.kind, old_loan.kind) {
+ let mut err = match (new_loan.kind, old_loan.kind) {
(ty::MutBorrow, ty::MutBorrow) => {
- span_err!(self.bccx, new_loan.span, E0499,
- "cannot borrow `{}`{} as mutable \
- more than once at a time",
- nl, new_loan_msg);
+ struct_span_err!(self.bccx, new_loan.span, E0499,
+ "cannot borrow `{}`{} as mutable \
+ more than once at a time",
+ nl, new_loan_msg)
}
(ty::UniqueImmBorrow, _) => {
- span_err!(self.bccx, new_loan.span, E0500,
- "closure requires unique access to `{}` \
- but {} is already borrowed{}",
- nl, ol_pronoun, old_loan_msg);
+ struct_span_err!(self.bccx, new_loan.span, E0500,
+ "closure requires unique access to `{}` \
+ but {} is already borrowed{}",
+ nl, ol_pronoun, old_loan_msg)
}
(_, ty::UniqueImmBorrow) => {
- span_err!(self.bccx, new_loan.span, E0501,
- "cannot borrow `{}`{} as {} because \
- previous closure requires unique access",
- nl, new_loan_msg, new_loan.kind.to_user_str());
+ struct_span_err!(self.bccx, new_loan.span, E0501,
+ "cannot borrow `{}`{} as {} because \
+ previous closure requires unique access",
+ nl, new_loan_msg, new_loan.kind.to_user_str())
}
(_, _) => {
- span_err!(self.bccx, new_loan.span, E0502,
- "cannot borrow `{}`{} as {} because \
- {} is also borrowed as {}{}",
- nl,
- new_loan_msg,
- new_loan.kind.to_user_str(),
- ol_pronoun,
- old_loan.kind.to_user_str(),
- old_loan_msg);
+ struct_span_err!(self.bccx, new_loan.span, E0502,
+ "cannot borrow `{}`{} as {} because \
+ {} is also borrowed as {}{}",
+ nl,
+ new_loan_msg,
+ new_loan.kind.to_user_str(),
+ ol_pronoun,
+ old_loan.kind.to_user_str(),
+ old_loan_msg)
}
- }
+ };
match new_loan.cause {
euv::ClosureCapture(span) => {
- self.bccx.span_note(
+ err.span_note(
span,
&format!("borrow occurs due to use of `{}` in closure",
nl));
}
};
- self.bccx.span_note(
+ err.span_note(
old_loan.span,
&format!("{}; {}", borrow_summary, rule_summary));
let old_loan_span = self.tcx().map.span(
old_loan.kill_scope.node_id(&self.tcx().region_maps));
- self.bccx.span_end_note(old_loan_span,
- "previous borrow ends here");
-
+ err.span_end_note(old_loan_span,
+ "previous borrow ends here");
+ err.emit();
return false;
}
match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
UseOk => { }
UseWhileBorrowed(loan_path, loan_span) => {
- span_err!(self.bccx, span, E0503,
- "cannot use `{}` because it was mutably borrowed",
- &self.bccx.loan_path_to_string(copy_path));
- self.bccx.span_note(
- loan_span,
- &format!("borrow of `{}` occurs here",
- &self.bccx.loan_path_to_string(&*loan_path))
- );
+ 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,
+ &format!("borrow of `{}` occurs here",
+ &self.bccx.loan_path_to_string(&*loan_path))
+ )
+ .emit();
}
}
}
match self.analyze_restrictions_on_use(id, move_path, ty::MutBorrow) {
UseOk => { }
UseWhileBorrowed(loan_path, loan_span) => {
- match move_kind {
+ let mut err = match move_kind {
move_data::Captured =>
- span_err!(self.bccx, span, E0504,
- "cannot move `{}` into closure because it is borrowed",
- &self.bccx.loan_path_to_string(move_path)),
+ struct_span_err!(self.bccx, span, E0504,
+ "cannot move `{}` into closure because it is borrowed",
+ &self.bccx.loan_path_to_string(move_path)),
move_data::Declared |
move_data::MoveExpr |
move_data::MovePat =>
- span_err!(self.bccx, span, E0505,
- "cannot move out of `{}` because it is borrowed",
- &self.bccx.loan_path_to_string(move_path))
+ struct_span_err!(self.bccx, span, E0505,
+ "cannot move out of `{}` because it is borrowed",
+ &self.bccx.loan_path_to_string(move_path))
};
- self.bccx.span_note(
+ err.span_note(
loan_span,
&format!("borrow of `{}` occurs here",
&self.bccx.loan_path_to_string(&*loan_path))
);
+ err.emit();
}
}
}
span: Span,
loan_path: &LoanPath<'tcx>,
loan: &Loan) {
- span_err!(self.bccx, span, E0506,
- "cannot assign to `{}` because it is borrowed",
- self.bccx.loan_path_to_string(loan_path));
- self.bccx.span_note(
- loan.span,
- &format!("borrow of `{}` occurs here",
- self.bccx.loan_path_to_string(loan_path)));
+ struct_span_err!(self.bccx, span, E0506,
+ "cannot assign to `{}` because it is borrowed",
+ self.bccx.loan_path_to_string(loan_path))
+ .span_note(loan.span,
+ &format!("borrow of `{}` occurs here",
+ self.bccx.loan_path_to_string(loan_path)))
+ .emit();
}
}
use rustc::middle::ty;
use syntax::ast;
use syntax::codemap;
+use syntax::errors::DiagnosticBuilder;
use rustc_front::hir;
pub struct MoveErrorCollector<'tcx> {
errors: &Vec<MoveError<'tcx>>) {
let grouped_errors = group_errors_with_same_origin(errors);
for error in &grouped_errors {
- report_cannot_move_out_of(bccx, error.move_from.clone());
+ let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
let mut is_first_note = true;
for move_to in &error.move_to_places {
- note_move_destination(bccx, move_to.span,
+ note_move_destination(&mut err, move_to.span,
move_to.name, is_first_note);
is_first_note = false;
}
+ err.emit();
}
}
// (keep in sync with gather_moves::check_and_get_illegal_move_origin )
fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
- move_from: mc::cmt<'tcx>) {
+ move_from: mc::cmt<'tcx>)
+ -> DiagnosticBuilder<'a> {
match move_from.cat {
Categorization::Deref(_, _, mc::BorrowedPtr(..)) |
Categorization::Deref(_, _, mc::Implicit(..)) |
Categorization::Deref(_, _, mc::UnsafePtr(..)) |
Categorization::StaticItem => {
- span_err!(bccx, move_from.span, E0507,
- "cannot move out of {}",
- move_from.descriptive_string(bccx.tcx));
+ struct_span_err!(bccx, move_from.span, E0507,
+ "cannot move out of {}",
+ move_from.descriptive_string(bccx.tcx))
}
Categorization::Interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
let expr = bccx.tcx.map.expect_expr(move_from.id);
if let hir::ExprIndex(..) = expr.node {
- span_err!(bccx, move_from.span, E0508,
- "cannot move out of type `{}`, \
- a non-copy fixed-size array",
- b.ty);
+ struct_span_err!(bccx, move_from.span, E0508,
+ "cannot move out of type `{}`, \
+ a non-copy fixed-size array",
+ b.ty)
+ } else {
+ bccx.span_bug(move_from.span, "this path should not cause illegal move");
+ unreachable!();
}
}
match b.ty.sty {
ty::TyStruct(def, _) |
ty::TyEnum(def, _) if def.has_dtor() => {
- span_err!(bccx, move_from.span, E0509,
- "cannot move out of type `{}`, \
- which defines the `Drop` trait",
- b.ty);
+ struct_span_err!(bccx, move_from.span, E0509,
+ "cannot move out of type `{}`, \
+ which defines the `Drop` trait",
+ b.ty)
},
_ => {
- bccx.span_bug(move_from.span, "this path should not cause illegal move")
+ bccx.span_bug(move_from.span, "this path should not cause illegal move");
+ unreachable!();
}
}
}
_ => {
- bccx.span_bug(move_from.span, "this path should not cause illegal move")
+ bccx.span_bug(move_from.span, "this path should not cause illegal move");
+ unreachable!();
}
}
}
-fn note_move_destination(bccx: &BorrowckCtxt,
+fn note_move_destination(err: &mut DiagnosticBuilder,
move_to_span: codemap::Span,
pat_name: ast::Name,
is_first_note: bool) {
if is_first_note {
- bccx.span_note(
+ err.span_note(
move_to_span,
"attempting to move value to here");
- bccx.fileline_help(
+ err.fileline_help(
move_to_span,
&format!("to prevent the move, \
- use `ref {0}` or `ref mut {0}` to capture value by \
- reference",
- pat_name));
+ use `ref {0}` or `ref mut {0}` to capture value by \
+ reference",
+ pat_name));
} else {
- bccx.span_note(move_to_span,
- &format!("and here (use `ref {0}` or `ref mut {0}`)",
+ err.span_note(move_to_span,
+ &format!("and here (use `ref {0}` or `ref mut {0}`)",
pat_name));
}
}
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
+use syntax::errors::DiagnosticBuilder;
use rustc_front::hir;
use rustc_front::hir::{FnDecl, Block};
}
// General fallback.
- self.span_err(
+ let mut db = self.struct_span_err(
err.span,
&self.bckerr_to_string(&err));
- self.note_and_explain_bckerr(err);
+ self.note_and_explain_bckerr(&mut db, err);
+ db.emit();
}
pub fn report_use_of_moved_value<'b>(&self,
MovedInCapture => "capture",
};
- let (ol, moved_lp_msg) = match the_move.kind {
+ let (ol, moved_lp_msg, mut err) = match the_move.kind {
move_data::Declared => {
- span_err!(
+ let err = struct_span_err!(
self.tcx.sess, use_span, E0381,
"{} of possibly uninitialized variable: `{}`",
verb,
self.loan_path_to_string(lp));
(self.loan_path_to_string(moved_lp),
- String::new())
+ String::new(),
+ err)
}
_ => {
// If moved_lp is something like `x.a`, and lp is something like `x.b`, we would
let msg = if !has_fork && partial { "partially " }
else if has_fork && !has_common { "collaterally "}
else { "" };
- span_err!(
+ let err = struct_span_err!(
self.tcx.sess, use_span, E0382,
"{} of {}moved value: `{}`",
verb, msg, nl);
- (ol, moved_lp_msg)
+ (ol, moved_lp_msg, err)
}
};
// multiple times. Avoid printing the same span and adjust the wording so it makes
// more sense that it's from multiple evalutations.
if expr_span == use_span {
- self.tcx.sess.note(
+ err.note(
&format!("`{}` was previously moved here{} because it has type `{}`, \
which is {}",
ol,
expr_ty,
suggestion));
} else {
- self.tcx.sess.span_note(
+ err.span_note(
expr_span,
&format!("`{}` moved here{} because it has type `{}`, which is {}",
ol,
move_data::MovePat => {
let pat_ty = self.tcx.node_id_to_type(the_move.id);
let span = self.tcx.map.span(the_move.id);
- self.tcx.sess.span_note(span,
+ err.span_note(span,
&format!("`{}` moved here{} because it has type `{}`, \
which is moved by default",
ol,
pat_ty));
match self.tcx.sess.codemap().span_to_snippet(span) {
Ok(string) => {
- self.tcx.sess.span_suggestion(
+ err.span_suggestion(
span,
&format!("if you would like to borrow the value instead, \
use a `ref` binding as shown:"),
format!("ref {}", string));
},
Err(_) => {
- self.tcx.sess.fileline_help(span,
+ err.fileline_help(span,
"use `ref` to override");
},
}
expr_ty,
("moved by default",
"make a copy and capture that instead to override"));
- self.tcx.sess.span_note(
+ err.span_note(
expr_span,
&format!("`{}` moved into closure environment here{} because it \
has type `{}`, which is {}",
moved_lp_msg,
moved_lp.ty,
suggestion));
- self.tcx.sess.fileline_help(expr_span, help);
+ err.fileline_help(expr_span, help);
}
}
+ err.emit();
fn move_suggestion<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
span: Span,
lp: &LoanPath<'tcx>,
assign:
&move_data::Assignment) {
- span_err!(
+ struct_span_err!(
self.tcx.sess, span, E0384,
"re-assignment of immutable variable `{}`",
- self.loan_path_to_string(lp));
- self.tcx.sess.span_note(assign.span, "prior assignment occurs here");
+ self.loan_path_to_string(lp))
+ .span_note(assign.span, "prior assignment occurs here")
+ .emit();
}
pub fn span_err(&self, s: Span, m: &str) {
self.tcx.sess.span_err(s, m);
}
- pub fn span_err_with_code(&self, s: Span, msg: &str, code: &str) {
- self.tcx.sess.span_err_with_code(s, msg, code);
+ pub fn struct_span_err(&self, s: Span, m: &str) -> DiagnosticBuilder<'a> {
+ self.tcx.sess.struct_span_err(s, m)
}
- pub fn span_bug(&self, s: Span, m: &str) {
- self.tcx.sess.span_bug(s, m);
- }
-
- pub fn span_note(&self, s: Span, m: &str) {
- self.tcx.sess.span_note(s, m);
+ pub fn struct_span_err_with_code(&self,
+ s: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ self.tcx.sess.struct_span_err_with_code(s, msg, code)
}
- pub fn span_end_note(&self, s: Span, m: &str) {
- self.tcx.sess.span_end_note(s, m);
+ pub fn span_err_with_code(&self, s: Span, msg: &str, code: &str) {
+ self.tcx.sess.span_err_with_code(s, msg, code);
}
- pub fn fileline_help(&self, s: Span, m: &str) {
- self.tcx.sess.fileline_help(s, m);
+ pub fn span_bug(&self, s: Span, m: &str) {
+ self.tcx.sess.span_bug(s, m);
}
pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String {
}
};
- match cause {
+ let mut err = match cause {
mc::AliasableOther => {
- span_err!(
+ struct_span_err!(
self.tcx.sess, span, E0385,
- "{} in an aliasable location", prefix);
+ "{} in an aliasable location", prefix)
}
mc::AliasableReason::UnaliasableImmutable => {
- span_err!(
+ struct_span_err!(
self.tcx.sess, span, E0386,
- "{} in an immutable container", prefix);
+ "{} in an immutable container", prefix)
}
mc::AliasableClosure(id) => {
- span_err!(
+ let mut err = struct_span_err!(
self.tcx.sess, span, E0387,
"{} in a captured outer variable in an `Fn` closure", prefix);
if let BorrowViolation(euv::ClosureCapture(_)) = kind {
// happen for nested closures, so we know the enclosing
// closure incorrectly accepts an `Fn` while it needs to
// be `FnMut`.
- span_help!(self.tcx.sess, self.tcx.map.span(id),
+ span_help!(&mut err, self.tcx.map.span(id),
"consider changing this to accept closures that implement `FnMut`");
} else {
- span_help!(self.tcx.sess, self.tcx.map.span(id),
+ span_help!(&mut err, self.tcx.map.span(id),
"consider changing this closure to take self by mutable reference");
}
+ err
}
mc::AliasableStatic |
mc::AliasableStaticMut => {
- span_err!(
+ struct_span_err!(
self.tcx.sess, span, E0388,
- "{} in a static location", prefix);
+ "{} in a static location", prefix)
}
mc::AliasableBorrowed => {
- span_err!(
+ struct_span_err!(
self.tcx.sess, span, E0389,
- "{} in a `&` reference", prefix);
+ "{} in a `&` reference", prefix)
}
- }
+ };
if is_closure {
- self.tcx.sess.fileline_help(
- span,
- "closures behind references must be called via `&mut`");
+ err.fileline_help(span,
+ "closures behind references must be called via `&mut`");
}
+ err.emit();
}
fn report_out_of_scope_escaping_closure_capture(&self,
{
let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt);
- span_err!(
- self.tcx.sess, err.span, E0373,
- "closure may outlive the current function, \
- but it borrows {}, \
- which is owned by the current function",
- cmt_path_or_string);
-
- self.tcx.sess.span_note(
- capture_span,
- &format!("{} is borrowed here",
- cmt_path_or_string));
-
let suggestion =
match self.tcx.sess.codemap().span_to_snippet(err.span) {
Ok(string) => format!("move {}", string),
Err(_) => format!("move |<args>| <body>")
};
- self.tcx.sess.span_suggestion(
- err.span,
- &format!("to force the closure to take ownership of {} \
- (and any other referenced variables), \
- use the `move` keyword, as shown:",
- cmt_path_or_string),
- suggestion);
+ struct_span_err!(self.tcx.sess, err.span, E0373,
+ "closure may outlive the current function, \
+ but it borrows {}, \
+ which is owned by the current function",
+ cmt_path_or_string)
+ .span_note(capture_span,
+ &format!("{} is borrowed here",
+ cmt_path_or_string))
+ .span_suggestion(err.span,
+ &format!("to force the closure to take ownership of {} \
+ (and any other referenced variables), \
+ use the `move` keyword, as shown:",
+ cmt_path_or_string),
+ suggestion)
+ .emit();
}
- pub fn note_and_explain_bckerr(&self, err: BckError<'tcx>) {
+ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) {
let code = err.code;
match code {
err_mutbl => {
_ => unreachable!()
};
if kind == ty::FnClosureKind {
- self.tcx.sess.span_help(
+ db.span_help(
self.tcx.map.span(upvar_id.closure_expr_id),
"consider changing this closure to take \
self by mutable reference");
if let Categorization::Local(local_id) = err.cmt.cat {
let span = self.tcx.map.span(local_id);
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- self.tcx.sess.span_suggestion(
+ db.span_suggestion(
span,
&format!("to make the {} mutable, use `mut` as shown:",
self.cmt_to_string(&err.cmt)),
err_out_of_scope(super_scope, sub_scope) => {
self.tcx.note_and_explain_region(
+ db,
"reference must be valid for ",
sub_scope,
"...");
self.tcx.note_and_explain_region(
+ db,
"...but borrowed value is only valid for ",
super_scope,
"");
if let Some(span) = statement_scope_span(self.tcx, super_scope) {
- self.tcx.sess.span_help(span,
- "consider using a `let` binding to increase its lifetime");
+ db.span_help(span,
+ "consider using a `let` binding to increase its lifetime");
}
}
None => self.cmt_to_string(&*err.cmt),
};
self.tcx.note_and_explain_region(
+ db,
&format!("{} would have to be valid for ",
descr),
loan_scope,
"...");
self.tcx.note_and_explain_region(
+ db,
&format!("...but {} is only valid for ", descr),
ptr_scope,
"");
None
}
_ => {
- session.span_err(a.span, "`crate_type` requires a value");
- session.note("for example: `#![crate_type=\"lib\"]`");
+ session.struct_span_err(a.span, "`crate_type` requires a value")
+ .note("for example: `#![crate_type=\"lib\"]`")
+ .emit();
None
}
}
fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) {
match lvl {
Level::Bug | Level::Fatal | Level::Error => {}
- Level::Warning | Level::Note | Level::Help => {
+ _ => {
return;
}
}
path_parameters: &PathParameters)
-> hir::PathParameters {
match *path_parameters {
- AngleBracketedParameters(ref data) =>
+ PathParameters::AngleBracketed(ref data) =>
hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(lctx, data)),
- ParenthesizedParameters(ref data) =>
+ PathParameters::Parenthesized(ref data) =>
hir::ParenthesizedParameters(lower_parenthesized_parameter_data(lctx, data)),
}
}
// no break */ }`) shouldn't be linted unless it actually
// recurs.
if !reached_exit_without_self_call && !self_call_spans.is_empty() {
- cx.span_lint(UNCONDITIONAL_RECURSION, sp,
- "function cannot return without recurring");
+ let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp,
+ "function cannot return without recurring");
// FIXME #19668: these could be span_lint_note's instead of this manual guard.
if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
- let sess = cx.sess();
// offer some help to the programmer.
for call in &self_call_spans {
- sess.span_note(*call, "recursive call site")
+ db.span_note(*call, "recursive call site");
}
- sess.fileline_help(sp, "a `loop` may express intention \
- better if this is on purpose")
+ db.fileline_help(sp, "a `loop` may express intention \
+ better if this is on purpose");
}
+ db.emit();
}
// all done
use syntax::parse;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
+use syntax::errors::FatalError;
use syntax::parse::token::InternedString;
use syntax::util::small_vector::SmallVector;
use rustc_front::intravisit::Visitor;
let lo = p.span.lo;
let body = match p.parse_all_token_trees() {
Ok(body) => body,
- Err(err) => panic!(err),
+ Err(mut err) => {
+ err.emit();
+ panic!(FatalError);
+ }
};
let span = mk_sp(lo, p.last_span.hi);
p.abort_if_errors();
let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
- 's' => ty::StaticExplicitSelfCategory,
- 'v' => ty::ByValueExplicitSelfCategory,
- '~' => ty::ByBoxExplicitSelfCategory,
+ 's' => ty::ExplicitSelfCategory::Static,
+ 'v' => ty::ExplicitSelfCategory::ByValue,
+ '~' => ty::ExplicitSelfCategory::ByBox,
// FIXME(#4846) expl. region
'&' => {
- ty::ByReferenceExplicitSelfCategory(
+ ty::ExplicitSelfCategory::ByReference(
ty::ReEmpty,
get_mutability(string.as_bytes()[1]))
}
let doc = cdata.lookup_item(id);
match item_sort(doc) {
Some('r') | Some('p') => {
- get_explicit_self(doc) == ty::StaticExplicitSelfCategory
+ get_explicit_self(doc) == ty::ExplicitSelfCategory::Static
}
_ => false
}
// Encode the base self type.
match *explicit_self {
- ty::StaticExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::Static => {
rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
}
- ty::ByValueExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::ByValue => {
rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
}
- ty::ByBoxExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::ByBox => {
rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
}
- ty::ByReferenceExplicitSelfCategory(_, m) => {
+ ty::ExplicitSelfCategory::ByReference(_, m) => {
// FIXME(#4846) encode custom lifetime
let ch = encode_mutability(m);
rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
encode_visibility(rbml_w, method_ty.vis);
encode_explicit_self(rbml_w, &method_ty.explicit_self);
match method_ty.explicit_self {
- ty::StaticExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::Static => {
encode_family(rbml_w, STATIC_METHOD_FAMILY);
}
_ => encode_family(rbml_w, METHOD_FAMILY)
path.clone().chain(Some(elem)));
match method_ty.explicit_self {
- ty::StaticExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::Static => {
encode_family(rbml_w,
STATIC_METHOD_FAMILY);
}
ecx.local_id(method_def_id));
is_nonstatic_method = method_ty.explicit_self !=
- ty::StaticExplicitSelfCategory;
+ ty::ExplicitSelfCategory::Static;
}
ty::TypeTraitItem(associated_type) => {
encode_name(rbml_w, associated_type.name);
use rustc_llvm::{False, ObjectFile, mk_section_iter};
use rustc_llvm::archive_ro::ArchiveRO;
use syntax::codemap::Span;
-use syntax::errors::Handler;
+use syntax::errors::DiagnosticBuilder;
use rustc_back::target::Target;
use std::cmp;
&Some(ref r) => format!(" which `{}` depends on",
r.ident)
};
- if !self.rejected_via_hash.is_empty() {
- span_err!(self.sess, self.span, E0460,
- "found possibly newer version of crate `{}`{}",
- self.ident, add);
+ let mut err = if !self.rejected_via_hash.is_empty() {
+ struct_span_err!(self.sess, self.span, E0460,
+ "found possibly newer version of crate `{}`{}",
+ self.ident, add)
} else if !self.rejected_via_triple.is_empty() {
- span_err!(self.sess, self.span, E0461,
- "couldn't find crate `{}` with expected target triple {}{}",
- self.ident, self.triple, add);
+ struct_span_err!(self.sess, self.span, E0461,
+ "couldn't find crate `{}` with expected target triple {}{}",
+ self.ident, self.triple, add)
} else if !self.rejected_via_kind.is_empty() {
- span_err!(self.sess, self.span, E0462,
- "found staticlib `{}` instead of rlib or dylib{}",
- self.ident, add);
+ struct_span_err!(self.sess, self.span, E0462,
+ "found staticlib `{}` instead of rlib or dylib{}",
+ self.ident, add)
} else {
- span_err!(self.sess, self.span, E0463,
- "can't find crate for `{}`{}",
- self.ident, add);
- }
+ struct_span_err!(self.sess, self.span, E0463,
+ "can't find crate for `{}`{}",
+ self.ident, add)
+ };
if !self.rejected_via_triple.is_empty() {
let mismatches = self.rejected_via_triple.iter();
for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
- self.sess.fileline_note(self.span,
+ err.fileline_note(self.span,
&format!("crate `{}`, path #{}, triple {}: {}",
self.ident, i+1, got, path.display()));
}
}
if !self.rejected_via_hash.is_empty() {
- self.sess.span_note(self.span, "perhaps this crate needs \
+ err.span_note(self.span, "perhaps this crate needs \
to be recompiled?");
let mismatches = self.rejected_via_hash.iter();
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
- self.sess.fileline_note(self.span,
+ err.fileline_note(self.span,
&format!("crate `{}` path #{}: {}",
self.ident, i+1, path.display()));
}
&None => {}
&Some(ref r) => {
for (i, path) in r.paths().iter().enumerate() {
- self.sess.fileline_note(self.span,
+ err.fileline_note(self.span,
&format!("crate `{}` path #{}: {}",
r.ident, i+1, path.display()));
}
}
}
if !self.rejected_via_kind.is_empty() {
- self.sess.fileline_help(self.span, "please recompile this crate using \
- --crate-type lib");
+ err.fileline_help(self.span, "please recompile this crate using \
+ --crate-type lib");
let mismatches = self.rejected_via_kind.iter();
for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
- self.sess.fileline_note(self.span,
- &format!("crate `{}` path #{}: {}",
- self.ident, i+1, path.display()));
+ err.fileline_note(self.span,
+ &format!("crate `{}` path #{}: {}",
+ self.ident, i+1, path.display()));
}
}
+
+ err.emit();
self.sess.abort_if_errors();
}
0 => None,
1 => Some(libraries.into_iter().next().unwrap()),
_ => {
- span_err!(self.sess, self.span, E0464,
- "multiple matching crates for `{}`",
- self.crate_name);
- self.sess.note("candidates:");
+ let mut err = struct_span_err!(self.sess, self.span, E0464,
+ "multiple matching crates for `{}`",
+ self.crate_name);
+ err.note("candidates:");
for lib in &libraries {
match lib.dylib {
Some((ref p, _)) => {
- self.sess.note(&format!("path: {}",
- p.display()));
+ err.note(&format!("path: {}",
+ p.display()));
}
None => {}
}
match lib.rlib {
Some((ref p, _)) => {
- self.sess.note(&format!("path: {}",
- p.display()));
+ err.note(&format!("path: {}",
+ p.display()));
}
None => {}
}
let data = lib.metadata.as_slice();
let name = decoder::get_crate_name(data);
- note_crate_name(self.sess.diagnostic(), &name);
+ note_crate_name(&mut err, &name);
}
+ err.emit();
None
}
}
}
}
+ let mut err: Option<DiagnosticBuilder> = None;
for (lib, kind) in m {
info!("{} reading metadata from: {}", flavor, lib.display());
let metadata = match get_metadata_section(self.target, &lib) {
// candidates have the same hash, so they're not actually
// duplicates that we should warn about.
if ret.is_some() && self.hash.is_none() {
- span_err!(self.sess, self.span, E0465,
- "multiple {} candidates for `{}` found",
- flavor, self.crate_name);
- self.sess.span_note(self.span,
- &format!(r"candidate #1: {}",
- ret.as_ref().unwrap().0
- .display()));
+ let mut e = struct_span_err!(self.sess, self.span, E0465,
+ "multiple {} candidates for `{}` found",
+ flavor, self.crate_name);
+ e.span_note(self.span,
+ &format!(r"candidate #1: {}",
+ ret.as_ref().unwrap().0
+ .display()));
+ if let Some(ref mut e) = err {
+ e.emit();
+ }
+ err = Some(e);
error = 1;
ret = None;
}
if error > 0 {
error += 1;
- self.sess.span_note(self.span,
- &format!(r"candidate #{}: {}", error,
- lib.display()));
+ err.as_mut().unwrap().span_note(self.span,
+ &format!(r"candidate #{}: {}", error,
+ lib.display()));
continue
}
*slot = Some(metadata);
ret = Some((lib, kind));
}
- return if error > 0 {None} else {ret}
+
+ if error > 0 {
+ err.unwrap().emit();
+ None
+ } else {
+ ret
+ }
}
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
return true
}
}
- sess.err(&format!("extern location for {} is of an unknown type: {}",
- self.crate_name, loc.display()));
- sess.help(&format!("file name should be lib*.rlib or {}*.{}",
- dylibname.0, dylibname.1));
+ sess.struct_err(&format!("extern location for {} is of an unknown type: {}",
+ self.crate_name, loc.display()))
+ .help(&format!("file name should be lib*.rlib or {}*.{}",
+ dylibname.0, dylibname.1))
+ .emit();
false
});
}
}
-pub fn note_crate_name(diag: &Handler, name: &str) {
- diag.note(&format!("crate name: {}", name));
+pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
+ err.note(&format!("crate name: {}", name));
}
impl ArchiveMetadata {
Some(node_id)
},
_ => {
- diagnostic.err("multiple plugin registration functions found");
+ let mut e = diagnostic.struct_err("multiple plugin registration functions found");
for &(_, span) in &finder.registrars {
- diagnostic.span_note(span, "one is here");
+ e.span_note(span, "one is here");
}
+ e.emit();
diagnostic.abort_if_errors();
unreachable!();
}
match result {
None => true,
Some((span, msg, note)) => {
- self.tcx.sess.span_err(span, &msg[..]);
- match note {
- Some((span, msg)) => {
- self.tcx.sess.span_note(span, &msg[..])
- }
- None => {},
+ let mut err = self.tcx.sess.struct_span_err(span, &msg[..]);
+ if let Some((span, msg)) = note {
+ err.span_note(span, &msg[..]);
}
+ err.emit();
false
},
}
fn check_sane_privacy(&self, item: &hir::Item) {
let check_inherited = |sp, vis, note: &str| {
if vis != hir::Inherited {
- span_err!(self.tcx.sess, sp, E0449, "unnecessary visibility qualifier");
+ let mut err = struct_span_err!(self.tcx.sess, sp, E0449,
+ "unnecessary visibility qualifier");
if !note.is_empty() {
- self.tcx.sess.span_note(sp, note);
+ err.span_note(sp, note);
}
+ err.emit();
}
};
use ParentLink::{self, ModuleParentLink, BlockParentLink};
use Resolver;
use resolve_imports::Shadowable;
-use {resolve_error, ResolutionError};
+use {resolve_error, resolve_struct_error, ResolutionError};
use self::DuplicateCheckingMode::*;
// Record an error here by looking up the namespace that had the duplicate
let ns_str = match ns { TypeNS => "type or module", ValueNS => "value" };
- resolve_error(self, sp, ResolutionError::DuplicateDefinition(ns_str, name));
+ let mut err = resolve_struct_error(self,
+ sp,
+ ResolutionError::DuplicateDefinition(ns_str,
+ name));
if let Some(sp) = child[ns].span() {
let note = format!("first definition of {} `{}` here", ns_str, name);
- self.session.span_note(sp, ¬e);
+ err.span_note(sp, ¬e);
}
+ err.emit();
child
}
}
})
.collect::<Vec<Span>>();
if mod_spans.len() > 1 {
- resolve_error(self,
+ let mut e = resolve_struct_error(self,
mod_spans[0],
ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
for other_span in mod_spans.iter().skip(1) {
- self.session
- .span_note(*other_span, "another `self` import appears here");
+ e.span_note(*other_span, "another `self` import appears here");
}
+ e.emit();
}
for source_item in source_items {
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
use syntax::attr::AttrMetaMethods;
-use syntax::parse::token::{self, special_names, special_idents};
use syntax::codemap::{self, Span, Pos};
+use syntax::errors::DiagnosticBuilder;
+use syntax::parse::token::{self, special_names, special_idents};
use syntax::util::lev_distance::find_best_match_for_name;
use rustc_front::intravisit::{self, FnKind, Visitor};
fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
span: syntax::codemap::Span,
resolution_error: ResolutionError<'b>) {
+ resolve_struct_error(resolver, span, resolution_error).emit();
+}
+
+fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
+ span: syntax::codemap::Span,
+ resolution_error: ResolutionError<'b>)
+ -> DiagnosticBuilder<'a> {
if !resolver.emit_errors {
- return;
+ return resolver.session.diagnostic().struct_dummy();
}
+
match resolution_error {
ResolutionError::TypeParametersFromOuterFunction => {
- span_err!(resolver.session,
- span,
- E0401,
- "can't use type parameters from outer function; try using a local type \
- parameter instead");
+ struct_span_err!(resolver.session,
+ span,
+ E0401,
+ "can't use type parameters from outer function; try using a local \
+ type parameter instead")
}
ResolutionError::OuterTypeParameterContext => {
- span_err!(resolver.session,
- span,
- E0402,
- "cannot use an outer type parameter in this context");
+ struct_span_err!(resolver.session,
+ span,
+ E0402,
+ "cannot use an outer type parameter in this context")
}
ResolutionError::NameAlreadyUsedInTypeParameterList(name) => {
- span_err!(resolver.session,
- span,
- E0403,
- "the name `{}` is already used for a type parameter in this type parameter \
- list",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0403,
+ "the name `{}` is already used for a type parameter in this type \
+ parameter list",
+ name)
}
ResolutionError::IsNotATrait(name) => {
- span_err!(resolver.session, span, E0404, "`{}` is not a trait", name);
+ struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
}
ResolutionError::UndeclaredTraitName(name) => {
- span_err!(resolver.session,
- span,
- E0405,
- "use of undeclared trait name `{}`",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0405,
+ "use of undeclared trait name `{}`",
+ name)
}
ResolutionError::UndeclaredAssociatedType => {
- span_err!(resolver.session, span, E0406, "undeclared associated type");
+ struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
}
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
- span_err!(resolver.session,
- span,
- E0407,
- "method `{}` is not a member of trait `{}`",
- method,
- trait_);
+ struct_span_err!(resolver.session,
+ span,
+ E0407,
+ "method `{}` is not a member of trait `{}`",
+ method,
+ trait_)
}
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
- span_err!(resolver.session,
- span,
- E0437,
- "type `{}` is not a member of trait `{}`",
- type_,
- trait_);
+ struct_span_err!(resolver.session,
+ span,
+ E0437,
+ "type `{}` is not a member of trait `{}`",
+ type_,
+ trait_)
}
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
- span_err!(resolver.session,
- span,
- E0438,
- "const `{}` is not a member of trait `{}`",
- const_,
- trait_);
+ struct_span_err!(resolver.session,
+ span,
+ E0438,
+ "const `{}` is not a member of trait `{}`",
+ const_,
+ trait_)
}
ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
- span_err!(resolver.session,
- span,
- E0408,
- "variable `{}` from pattern #1 is not bound in pattern #{}",
- variable_name,
- pattern_number);
+ struct_span_err!(resolver.session,
+ span,
+ E0408,
+ "variable `{}` from pattern #1 is not bound in pattern #{}",
+ variable_name,
+ pattern_number)
}
ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
- span_err!(resolver.session,
- span,
- E0409,
- "variable `{}` is bound with different mode in pattern #{} than in pattern \
- #1",
- variable_name,
- pattern_number);
+ struct_span_err!(resolver.session,
+ span,
+ E0409,
+ "variable `{}` is bound with different mode in pattern #{} than in \
+ pattern #1",
+ variable_name,
+ pattern_number)
}
ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => {
- span_err!(resolver.session,
- span,
- E0410,
- "variable `{}` from pattern #{} is not bound in pattern #1",
- variable_name,
- pattern_number);
+ struct_span_err!(resolver.session,
+ span,
+ E0410,
+ "variable `{}` from pattern #{} is not bound in pattern #1",
+ variable_name,
+ pattern_number)
}
ResolutionError::SelfUsedOutsideImplOrTrait => {
- span_err!(resolver.session,
- span,
- E0411,
- "use of `Self` outside of an impl or trait");
+ struct_span_err!(resolver.session,
+ span,
+ E0411,
+ "use of `Self` outside of an impl or trait")
}
ResolutionError::UseOfUndeclared(kind, name) => {
- span_err!(resolver.session,
- span,
- E0412,
- "use of undeclared {} `{}`",
- kind,
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0412,
+ "use of undeclared {} `{}`",
+ kind,
+ name)
}
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
- span_err!(resolver.session,
- span,
- E0413,
- "declaration of `{}` shadows an enum variant or unit-like struct in scope",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0413,
+ "declaration of `{}` shadows an enum variant \
+ or unit-like struct in scope",
+ name)
}
ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => {
- span_err!(resolver.session,
- span,
- E0414,
- "only irrefutable patterns allowed here");
- resolver.session.span_note(span,
- "there already is a constant in scope sharing the same \
- name as this pattern");
+ let mut err = struct_span_err!(resolver.session,
+ span,
+ E0414,
+ "only irrefutable patterns allowed here");
+ err.span_note(span,
+ "there already is a constant in scope sharing the same \
+ name as this pattern");
if let Some(sp) = resolver.ast_map.span_if_local(did) {
- resolver.session.span_note(sp, "constant defined here");
+ err.span_note(sp, "constant defined here");
}
if let Some(directive) = resolver.current_module
.import_resolutions
.borrow()
.get(&name) {
let item = resolver.ast_map.expect_item(directive.value_ns.id);
- resolver.session.span_note(item.span, "constant imported here");
+ err.span_note(item.span, "constant imported here");
}
+ err
}
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
- span_err!(resolver.session,
- span,
- E0415,
- "identifier `{}` is bound more than once in this parameter list",
- identifier);
+ struct_span_err!(resolver.session,
+ span,
+ E0415,
+ "identifier `{}` is bound more than once in this parameter list",
+ identifier)
}
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
- span_err!(resolver.session,
- span,
- E0416,
- "identifier `{}` is bound more than once in the same pattern",
- identifier);
+ struct_span_err!(resolver.session,
+ span,
+ E0416,
+ "identifier `{}` is bound more than once in the same pattern",
+ identifier)
}
ResolutionError::StaticVariableReference => {
- span_err!(resolver.session,
- span,
- E0417,
- "static variables cannot be referenced in a pattern, use a `const` instead");
+ struct_span_err!(resolver.session,
+ span,
+ E0417,
+ "static variables cannot be referenced in a pattern, use a \
+ `const` instead")
}
ResolutionError::NotAnEnumVariantStructOrConst(name) => {
- span_err!(resolver.session,
- span,
- E0418,
- "`{}` is not an enum variant, struct or const",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0418,
+ "`{}` is not an enum variant, struct or const",
+ name)
}
ResolutionError::UnresolvedEnumVariantStructOrConst(name) => {
- span_err!(resolver.session,
- span,
- E0419,
- "unresolved enum variant, struct or const `{}`",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0419,
+ "unresolved enum variant, struct or const `{}`",
+ name)
}
ResolutionError::NotAnAssociatedConst(name) => {
- span_err!(resolver.session,
- span,
- E0420,
- "`{}` is not an associated const",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0420,
+ "`{}` is not an associated const",
+ name)
}
ResolutionError::UnresolvedAssociatedConst(name) => {
- span_err!(resolver.session,
- span,
- E0421,
- "unresolved associated const `{}`",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0421,
+ "unresolved associated const `{}`",
+ name)
}
ResolutionError::DoesNotNameAStruct(name) => {
- span_err!(resolver.session,
- span,
- E0422,
- "`{}` does not name a structure",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0422,
+ "`{}` does not name a structure",
+ name)
}
ResolutionError::StructVariantUsedAsFunction(path_name) => {
- 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);
+ 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)
}
ResolutionError::SelfNotAvailableInStaticMethod => {
- span_err!(resolver.session,
- span,
- E0424,
- "`self` is not available in a static method. Maybe a `self` argument is \
- missing?");
+ struct_span_err!(resolver.session,
+ span,
+ E0424,
+ "`self` is not available in a static method. Maybe a `self` \
+ argument is missing?")
}
ResolutionError::UnresolvedName(path, msg, context) => {
- span_err!(resolver.session,
- span,
- E0425,
- "unresolved name `{}`{}",
- path,
- msg);
+ let mut err = struct_span_err!(resolver.session,
+ span,
+ E0425,
+ "unresolved name `{}`{}",
+ path,
+ msg);
match context {
UnresolvedNameContext::Other => {} // no help available
}
if !help_msg.is_empty() {
- resolver.session.fileline_help(span, &help_msg);
+ err.fileline_help(span, &help_msg);
}
}
}
+ err
}
ResolutionError::UndeclaredLabel(name) => {
- span_err!(resolver.session,
- span,
- E0426,
- "use of undeclared label `{}`",
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0426,
+ "use of undeclared label `{}`",
+ name)
}
ResolutionError::CannotUseRefBindingModeWith(descr) => {
- span_err!(resolver.session,
- span,
- E0427,
- "cannot use `ref` binding mode with {}",
- descr);
+ struct_span_err!(resolver.session,
+ span,
+ E0427,
+ "cannot use `ref` binding mode with {}",
+ descr)
}
ResolutionError::DuplicateDefinition(namespace, name) => {
- span_err!(resolver.session,
- span,
- E0428,
- "duplicate definition of {} `{}`",
- namespace,
- name);
+ struct_span_err!(resolver.session,
+ span,
+ E0428,
+ "duplicate definition of {} `{}`",
+ namespace,
+ name)
}
ResolutionError::SelfImportsOnlyAllowedWithin => {
- span_err!(resolver.session,
- span,
- E0429,
- "{}",
- "`self` imports are only allowed within a { } list");
+ struct_span_err!(resolver.session,
+ span,
+ E0429,
+ "{}",
+ "`self` imports are only allowed within a { } list")
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
- span_err!(resolver.session,
- span,
- E0430,
- "`self` import can only appear once in the list");
+ struct_span_err!(resolver.session,
+ span,
+ E0430,
+ "`self` import can only appear once in the list")
}
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
- span_err!(resolver.session,
- span,
- E0431,
- "`self` import can only appear in an import list with a non-empty prefix");
+ struct_span_err!(resolver.session,
+ span,
+ E0431,
+ "`self` import can only appear in an import list with a \
+ non-empty prefix")
}
ResolutionError::UnresolvedImport(name) => {
let msg = match name {
Some((n, p)) => format!("unresolved import `{}`{}", n, p),
None => "unresolved import".to_owned(),
};
- span_err!(resolver.session, span, E0432, "{}", msg);
+ struct_span_err!(resolver.session, span, E0432, "{}", msg)
}
ResolutionError::FailedToResolve(msg) => {
- span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg);
+ struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg)
}
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
- span_err!(resolver.session,
- span,
- E0434,
- "{}",
- "can't capture dynamic environment in a fn item; use the || { ... } \
- closure form instead");
+ struct_span_err!(resolver.session,
+ span,
+ E0434,
+ "{}",
+ "can't capture dynamic environment in a fn item; use the || { ... } \
+ closure form instead")
}
ResolutionError::AttemptToUseNonConstantValueInConstant => {
- span_err!(resolver.session,
- span,
- E0435,
- "attempt to use a non-constant value in a constant");
+ struct_span_err!(resolver.session,
+ span,
+ E0435,
+ "attempt to use a non-constant value in a constant")
}
}
}
debug!("(resolving trait) found trait def: {:?}", path_res);
Ok(path_res)
} else {
- resolve_error(self,
- trait_path.span,
- ResolutionError::IsNotATrait(&*path_names_to_string(trait_path,
- path_depth)));
+ let mut err =
+ resolve_struct_error(self,
+ trait_path.span,
+ ResolutionError::IsNotATrait(&*path_names_to_string(trait_path,
+ path_depth)));
// If it's a typedef, give a note
if let DefTy(..) = path_res.base_def {
- self.session
- .span_note(trait_path.span, "`type` aliases cannot be used for traits");
+ err.span_note(trait_path.span,
+ "`type` aliases cannot be used for traits");
}
+ err.emit();
Err(())
}
} else {
if let DefVariant(_, _, true) = path_res.base_def {
let path_name = path_names_to_string(path, 0);
- resolve_error(self,
- expr.span,
- ResolutionError::StructVariantUsedAsFunction(&*path_name));
+ let mut err = resolve_struct_error(self,
+ expr.span,
+ ResolutionError::StructVariantUsedAsFunction(&*path_name));
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
path_name);
if self.emit_errors {
- self.session.fileline_help(expr.span, &msg);
+ err.fileline_help(expr.span, &msg);
} else {
- self.session.span_help(expr.span, &msg);
+ err.span_help(expr.span, &msg);
}
+ err.emit();
self.record_def(expr.id, err_path_resolution());
} else {
// Write the result into the def map.
self.record_def(expr.id, err_path_resolution());
match type_res.map(|r| r.base_def) {
Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
- resolve_error(
- self,
- expr.span,
- ResolutionError::StructVariantUsedAsFunction(
- &*path_name)
- );
+ let mut err = resolve_struct_error(self,
+ expr.span,
+ ResolutionError::StructVariantUsedAsFunction(&*path_name));
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
path_name);
if self.emit_errors {
- self.session.fileline_help(expr.span, &msg);
+ err.fileline_help(expr.span, &msg);
} else {
- self.session.span_help(expr.span, &msg);
+ err.span_help(expr.span, &msg);
}
+ err.emit();
}
_ => {
// Keep reporting some errors even if they're ignored above.
let note_msg = format!("Consider marking `{}` as `pub` in the imported \
module",
source);
- span_err!(self.resolver.session, directive.span, E0364, "{}", &msg);
- self.resolver.session.span_note(directive.span, ¬e_msg);
+ struct_span_err!(self.resolver.session, directive.span, E0364, "{}", &msg)
+ .span_note(directive.span, ¬e_msg)
+ .emit();
pub_err = true;
}
if directive.is_public && child_name_bindings.value_ns.
let msg = format!("`{}` is private, and cannot be reexported", source);
let note_msg = format!("Consider declaring module `{}` as a `pub mod`",
source);
- span_err!(self.resolver.session, directive.span, E0365, "{}", &msg);
- self.resolver.session.span_note(directive.span, ¬e_msg);
+ struct_span_err!(self.resolver.session, directive.span, E0365, "{}", &msg)
+ .span_note(directive.span, ¬e_msg)
+ .emit();
}
if !pub_err && directive.is_public && child_name_bindings.type_ns.
defined_with(DefModifiers::PRIVATE_VARIANT) {
}
ValueNS => "value",
};
- span_err!(self.resolver.session,
- import_span,
- E0252,
- "a {} named `{}` has already been imported in this module",
- ns_word,
- name);
let use_id = import_resolution[namespace].id;
let item = self.resolver.ast_map.expect_item(use_id);
- // item is syntax::ast::Item;
- span_note!(self.resolver.session,
+ let mut err = struct_span_err!(self.resolver.session,
+ import_span,
+ E0252,
+ "a {} named `{}` has already been imported \
+ in this module",
+ ns_word,
+ name);
+ span_note!(&mut err,
item.span,
"previous import of `{}` here",
name);
+ err.emit();
}
Some(_) | None => {}
}
match import.value_ns.target {
Some(ref target) if target.shadowable != Shadowable::Always => {
if let Some(ref value) = *name_bindings.value_ns.borrow() {
- span_err!(self.resolver.session,
- import_span,
- E0255,
- "import `{}` conflicts with value in this module",
- name);
+ let mut err = struct_span_err!(self.resolver.session,
+ import_span,
+ E0255,
+ "import `{}` conflicts with \
+ value in this module",
+ name);
if let Some(span) = value.span {
- self.resolver.session.span_note(span, "conflicting value here");
+ err.span_note(span, "conflicting value here");
}
+ err.emit();
}
}
Some(_) | None => {}
("trait in this module", "note conflicting trait here"),
_ => ("type in this module", "note conflicting type here"),
};
- span_err!(self.resolver.session,
- import_span,
- E0256,
- "import `{}` conflicts with {}",
- name,
- what);
+ let mut err = struct_span_err!(self.resolver.session,
+ import_span,
+ E0256,
+ "import `{}` conflicts with {}",
+ name,
+ what);
if let Some(span) = ty.span {
- self.resolver.session.span_note(span, note);
+ err.span_note(span, note);
}
+ err.emit();
}
}
Some(_) | None => {}
Ok(prog) => {
let o = prog.wait_with_output().unwrap();
if !o.status.success() {
- sess.err(&format!("{:?} failed with: {}", cmd, o.status));
- sess.note(&format!("stdout ---\n{}",
- str::from_utf8(&o.stdout).unwrap()));
- sess.note(&format!("stderr ---\n{}",
- str::from_utf8(&o.stderr).unwrap()));
+ sess.struct_err(&format!("{:?} failed with: {}", cmd, o.status))
+ .note(&format!("stdout ---\n{}",
+ str::from_utf8(&o.stdout).unwrap()))
+ .note(&format!("stderr ---\n{}",
+ str::from_utf8(&o.stderr).unwrap()))
+ .emit();
sess.abort_if_errors();
}
o
ab.build();
if !all_native_libs.is_empty() {
- sess.note("link against the following native artifacts when linking against \
- this static library");
- sess.note("the order and any duplication can be significant on some platforms, \
- and so may need to be preserved");
+ sess.note_without_error("link against the following native artifacts when linking against \
+ this static library");
+ sess.note_without_error("the order and any duplication can be significant on some \
+ platforms, and so may need to be preserved");
}
for &(kind, ref lib) in &all_native_libs {
NativeLibraryKind::NativeUnknown => "library",
NativeLibraryKind::NativeFramework => "framework",
};
- sess.note(&format!("{}: {}", name, *lib));
+ sess.note_without_error(&format!("{}: {}", name, *lib));
}
}
})
}
if !prog.status.success() {
- sess.err(&format!("linking with `{}` failed: {}",
- pname,
- prog.status));
- sess.note(&format!("{:?}", &cmd));
let mut output = prog.stderr.clone();
output.extend_from_slice(&prog.stdout);
- sess.note(&*escape_string(&output[..]));
+ sess.struct_err(&format!("linking with `{}` failed: {}",
+ pname,
+ prog.status))
+ .note(&format!("{:?}", &cmd))
+ .note(&*escape_string(&output[..]))
+ .emit();
sess.abort_if_errors();
}
info!("linker stderr:\n{}", escape_string(&prog.stderr[..]));
name_extra: &str,
output_names: &config::OutputFilenames) {
if sess.opts.cg.prefer_dynamic {
- sess.err("cannot prefer dynamic linking when performing LTO");
- sess.note("only 'staticlib' and 'bin' outputs are supported with LTO");
+ sess.struct_err("cannot prefer dynamic linking when performing LTO")
+ .note("only 'staticlib' and 'bin' outputs are supported with LTO")
+ .emit();
sess.abort_if_errors();
}
}
None => {
- cgcx.handler.err(msg);
- cgcx.handler.note("build without -C codegen-units for more exact errors");
+ cgcx.handler.struct_err(msg)
+ .note("build without -C codegen-units for more exact errors")
+ .emit();
}
}
}
if enabled {
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
- cgcx.handler.note(&format!("optimization {} for {} at {}: {}",
- opt.kind.describe(),
- pass_name,
- if loc.is_empty() { "[unknown]" } else { &*loc },
- llvm::twine_to_string(opt.message)));
+ cgcx.handler.note_without_error(&format!("optimization {} for {} at {}: {}",
+ opt.kind.describe(),
+ pass_name,
+ if loc.is_empty() { "[unknown]" } else { &*loc },
+ llvm::twine_to_string(opt.message)));
}
}
match cmd.output() {
Ok(prog) => {
if !prog.status.success() {
- sess.err(&format!("linking with `{}` failed: {}",
- pname,
- prog.status));
- sess.note(&format!("{:?}", &cmd));
let mut note = prog.stderr.clone();
note.extend_from_slice(&prog.stdout);
- sess.note(str::from_utf8(¬e[..]).unwrap());
+
+ sess.struct_err(&format!("linking with `{}` failed: {}",
+ pname,
+ prog.status))
+ .note(&format!("{:?}", &cmd))
+ .note(str::from_utf8(¬e[..]).unwrap())
+ .emit();
sess.abort_if_errors();
}
},
def::DefMethod(did) => {
let ti = self.tcx.impl_or_trait_item(did);
if let ty::MethodTraitItem(m) = ti {
- if m.explicit_self == ty::StaticExplicitSelfCategory {
+ if m.explicit_self == ty::ExplicitSelfCategory::Static {
self.write_sub_path_trait_truncated(path);
}
}
}
);
+ // FIXME(#30505) Should use logging for this.
if print_info {
let llty = type_of::sizing_type_of(ccx, ty);
let sess = &ccx.tcx().sess;
- sess.span_note(sp, &*format!("total size: {} bytes", llsize_of_real(ccx, llty)));
+ sess.span_note_without_error(sp,
+ &*format!("total size: {} bytes", llsize_of_real(ccx, llty)));
match *avar {
adt::General(..) => {
for (i, var) in enum_def.variants.iter().enumerate() {
ccx.tcx()
.sess
- .span_note(var.span, &*format!("variant data: {} bytes", sizes[i]));
+ .span_note_without_error(var.span,
+ &*format!("variant data: {} bytes", sizes[i]));
}
}
_ => {}
if !is_allow && largest > slargest * 3 && slargest > 0 {
// Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
// pass for the latter already ran.
- lint::raw_emit_lint(&ccx.tcx().sess,
- lint::builtin::VARIANT_SIZE_DIFFERENCES,
- *lvlsrc.unwrap(),
- Some(sp),
- &format!("enum variant is more than three times larger ({} bytes) \
- than the next largest (ignoring padding)",
- largest));
-
- ccx.sess().span_note(enum_def.variants[largest_index].span,
- "this variant is the largest");
+ lint::raw_struct_lint(&ccx.tcx().sess,
+ lint::builtin::VARIANT_SIZE_DIFFERENCES,
+ *lvlsrc.unwrap(),
+ Some(sp),
+ &format!("enum variant is more than three times larger ({} bytes) \
+ than the next largest (ignoring padding)",
+ largest))
+ .span_note(enum_def.variants[largest_index].span,
+ "this variant is the largest")
+ .emit();
}
}
let llfty = Type::func(&[ccx.int_type(), Type::i8p(ccx).ptr_to()], &ccx.int_type());
let llfn = declare::define_cfn(ccx, "main", llfty, ccx.tcx().mk_nil()).unwrap_or_else(|| {
- ccx.sess().span_err(sp, "entry symbol `main` defined multiple times");
// FIXME: We should be smart and show a better diagnostic here.
- ccx.sess().help("did you use #[no_mangle] on `fn main`? Use #[start] instead");
+ ccx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times")
+ .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
+ .emit();
ccx.sess().abort_if_errors();
panic!();
});
if !tcx.sess.features.borrow().simd_ffi {
let check = |ast_ty: &hir::Ty, ty: ty::Ty| {
if ty.is_simd() {
- tcx.sess.span_err(ast_ty.span,
+ tcx.sess.struct_span_err(ast_ty.span,
&format!("use of SIMD type `{}` in FFI is highly experimental and \
may result in invalid code",
- pprust::ty_to_string(ast_ty)));
- tcx.sess.fileline_help(ast_ty.span,
- "add #![feature(simd_ffi)] to the crate attributes to enable");
+ pprust::ty_to_string(ast_ty)))
+ .fileline_help(ast_ty.span,
+ "add #![feature(simd_ffi)] to the crate attributes to enable")
+ .emit();
}
};
let sig = &ty.sig.0;
use llvm::ValueRef;
use rustc::middle::ty::{self, Ty};
+use middle::ty::cast::{CastTy, IntTy};
use rustc::mir::repr as mir;
use trans::asm;
}
}
}
- mir::CastKind::Misc => unimplemented!()
+ mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
+ debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
+ let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
+ let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+ let ll_t_in = type_of::arg_type_of(bcx.ccx(), operand.ty);
+ let ll_t_out = type_of::arg_type_of(bcx.ccx(), cast_ty);
+ let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
+ let repr = adt::represent_type(bcx.ccx(), operand.ty);
+ let llval = operand.immediate();
+ let discr = adt::trans_get_discr(bcx, &*repr, llval, None);
+ (discr, common::val_ty(discr), adt::is_discr_signed(&*repr))
+ } else {
+ (operand.immediate(), ll_t_in, operand.ty.is_signed())
+ };
+
+ let newval = match (r_t_in, r_t_out) {
+ (CastTy::Int(_), CastTy::Int(_)) => {
+ let srcsz = ll_t_in.int_width();
+ let dstsz = ll_t_out.int_width();
+ if srcsz == dstsz {
+ build::BitCast(bcx, llval, ll_t_out)
+ } else if srcsz > dstsz {
+ build::Trunc(bcx, llval, ll_t_out)
+ } else if signed {
+ build::SExt(bcx, llval, ll_t_out)
+ } else {
+ build::ZExt(bcx, llval, ll_t_out)
+ }
+ }
+ (CastTy::Float, CastTy::Float) => {
+ let srcsz = ll_t_in.float_width();
+ let dstsz = ll_t_out.float_width();
+ if dstsz > srcsz {
+ build::FPExt(bcx, llval, ll_t_out)
+ } else if srcsz > dstsz {
+ build::FPTrunc(bcx, llval, ll_t_out)
+ } else {
+ llval
+ }
+ }
+ (CastTy::Ptr(_), CastTy::Ptr(_)) |
+ (CastTy::FnPtr, CastTy::Ptr(_)) |
+ (CastTy::RPtr(_), CastTy::Ptr(_)) =>
+ build::PointerCast(bcx, llval, ll_t_out),
+ (CastTy::Ptr(_), CastTy::Int(_)) |
+ (CastTy::FnPtr, CastTy::Int(_)) =>
+ build::PtrToInt(bcx, llval, ll_t_out),
+ (CastTy::Int(_), CastTy::Ptr(_)) =>
+ build::IntToPtr(bcx, llval, ll_t_out),
+ (CastTy::Int(_), CastTy::Float) if signed =>
+ build::SIToFP(bcx, llval, ll_t_out),
+ (CastTy::Int(_), CastTy::Float) =>
+ build::UIToFP(bcx, llval, ll_t_out),
+ (CastTy::Float, CastTy::Int(IntTy::I)) =>
+ build::FPToSI(bcx, llval, ll_t_out),
+ (CastTy::Float, CastTy::Int(_)) =>
+ build::FPToUI(bcx, llval, ll_t_out),
+ _ => bcx.ccx().sess().bug(
+ &format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
+ )
+ };
+ OperandValue::Immediate(newval)
+ }
+ mir::CastKind::Misc => { // Casts from a fat-ptr.
+ let ll_cast_ty = type_of::arg_type_of(bcx.ccx(), cast_ty);
+ let ll_from_ty = type_of::arg_type_of(bcx.ccx(), operand.ty);
+ if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
+ if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
+ let ll_cft = ll_cast_ty.field_types();
+ let ll_fft = ll_from_ty.field_types();
+ let data_cast = build::PointerCast(bcx, data_ptr, ll_cft[0]);
+ assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
+ OperandValue::FatPtr(data_cast, meta_ptr)
+ } else { // cast to thin-ptr
+ // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
+ // pointer-cast of that pointer to desired pointer type.
+ let llval = build::PointerCast(bcx, data_ptr, ll_cast_ty);
+ OperandValue::Immediate(llval)
+ }
+ } else {
+ panic!("Unexpected non-FatPtr operand")
+ }
+ }
};
(bcx, OperandRef {
val: val,
use syntax::{abi, ast};
use syntax::codemap::{Span, Pos};
+use syntax::errors::DiagnosticBuilder;
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::parse::token;
}
fn report_elision_failure(
- tcx: &ty::ctxt,
+ db: &mut DiagnosticBuilder,
default_span: Span,
params: Vec<ElisionFailureInfo>)
{
}
if len == 0 {
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"this function's return type contains a borrowed value, but \
there is no value for it to be borrowed from");
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"consider giving it a 'static lifetime");
} else if !any_lifetimes {
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"this function's return type contains a borrowed value with \
an elided lifetime, but the lifetime cannot be derived from \
the arguments");
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"consider giving it an explicit bounded or 'static \
lifetime");
} else if len == 1 {
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"this function's return type contains a borrowed value, but \
the signature does not say which {} it is borrowed from",
m);
} else {
- fileline_help!(tcx.sess, default_span,
+ fileline_help!(db, default_span,
"this function's return type contains a borrowed value, but \
the signature does not say whether it is borrowed from {}",
m);
None => match rscope.anon_regions(default_span, 1) {
Ok(rs) => rs[0],
Err(params) => {
- span_err!(this.tcx().sess, default_span, E0106,
- "missing lifetime specifier");
+ let mut err = struct_span_err!(this.tcx().sess, default_span, E0106,
+ "missing lifetime specifier");
if let Some(params) = params {
- report_elision_failure(this.tcx(), default_span, params);
+ report_elision_failure(&mut err, default_span, params);
}
+ err.emit();
ty::ReStatic
}
}
}
}
_ => {
- span_err!(this.tcx().sess, ty.span, E0178,
- "expected a path on the left-hand side of `+`, not `{}`",
- pprust::ty_to_string(ty));
+ let mut err = struct_span_err!(this.tcx().sess, ty.span, E0178,
+ "expected a path on the left-hand side of `+`, not `{}`",
+ pprust::ty_to_string(ty));
let hi = bounds.iter().map(|x| match *x {
hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
hir::RegionTyParamBound(ref r) => r.span.hi,
match (&ty.node, full_span) {
(&hir::TyRptr(None, ref mut_ty), Some(full_span)) => {
let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
- this.tcx().sess
- .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
- format!("&{}({} +{})",
- mutbl_str,
- pprust::ty_to_string(&*mut_ty.ty),
- pprust::bounds_to_string(bounds)));
+ err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
+ format!("&{}({} +{})",
+ mutbl_str,
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds)));
}
(&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
- this.tcx().sess
- .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
- format!("&{} {}({} +{})",
- pprust::lifetime_to_string(lt),
- mutbl_str,
- pprust::ty_to_string(&*mut_ty.ty),
- pprust::bounds_to_string(bounds)));
+ err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
+ format!("&{} {}({} +{})",
+ pprust::lifetime_to_string(lt),
+ mutbl_str,
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds)));
}
_ => {
- fileline_help!(this.tcx().sess, ty.span,
+ fileline_help!(&mut err, ty.span,
"perhaps you forgot parentheses? (per RFC 438)");
}
}
+ err.emit();
Err(ErrorReported)
}
}
traits::astconv_object_safety_violations(tcx, principal.def_id());
if !object_safety_violations.is_empty() {
traits::report_object_safety_error(
- tcx, span, principal.def_id(), object_safety_violations);
+ tcx, span, principal.def_id(), object_safety_violations)
+ .emit();
return tcx.types.err;
}
}
if bounds.len() > 1 {
- span_err!(tcx.sess, span, E0221,
- "ambiguous associated type `{}` in bounds of `{}`",
- assoc_name,
- ty_param_name);
+ let mut err = struct_span_err!(tcx.sess, span, E0221,
+ "ambiguous associated type `{}` in bounds of `{}`",
+ assoc_name,
+ ty_param_name);
for bound in &bounds {
- span_note!(tcx.sess, span,
+ span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
bound);
}
+ err.emit();
}
Ok(bounds[0].clone())
}
}
Err(ref r) => {
- span_err!(tcx.sess, r.span, E0250,
- "array length constant evaluation error: {}",
- r.description());
+ let mut err = struct_span_err!(tcx.sess, r.span, E0250,
+ "array length constant evaluation error: {}",
+ r.description());
if !ast_ty.span.contains(r.span) {
- span_note!(tcx.sess, ast_ty.span, "for array length here")
+ span_note!(&mut err, ast_ty.span, "for array length here")
}
+ err.emit();
this.tcx().types.err
}
}
// reference) in the arguments, then any anonymous regions in the output
// have that lifetime.
let implied_output_region = match explicit_self_category {
- Some(ty::ByReferenceExplicitSelfCategory(region, _)) => Ok(region),
+ Some(ty::ExplicitSelfCategory::ByReference(region, _)) => Ok(region),
_ => find_implied_output_region(this.tcx(), &arg_tys, arg_pats)
};
{
let self_ty = self_info.untransformed_self_ty;
return match self_info.explicit_self.node {
- hir::SelfStatic => (None, Some(ty::StaticExplicitSelfCategory)),
+ hir::SelfStatic => (None, Some(ty::ExplicitSelfCategory::Static)),
hir::SelfValue(_) => {
- (Some(self_ty), Some(ty::ByValueExplicitSelfCategory))
+ (Some(self_ty), Some(ty::ExplicitSelfCategory::ByValue))
}
hir::SelfRegion(ref lifetime, mutability, _) => {
let region =
ty: self_ty,
mutbl: mutability
})),
- Some(ty::ByReferenceExplicitSelfCategory(region, mutability)))
+ Some(ty::ExplicitSelfCategory::ByReference(region, mutability)))
}
hir::SelfExplicit(ref ast_type, _) => {
let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
// ```
// impl Foo for &T {
// // Legal declarations:
- // fn method1(self: &&T); // ByReferenceExplicitSelfCategory
- // fn method2(self: &T); // ByValueExplicitSelfCategory
- // fn method3(self: Box<&T>); // ByBoxExplicitSelfCategory
+ // fn method1(self: &&T); // ExplicitSelfCategory::ByReference
+ // fn method2(self: &T); // ExplicitSelfCategory::ByValue
+ // fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox
//
// // Invalid cases will be caught later by `check_method_self_type`:
- // fn method_err1(self: &mut T); // ByReferenceExplicitSelfCategory
+ // fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference
// }
// ```
//
// call it by-ref, by-box as appropriate. For method1, for
// example, the impl type has one modifier, but the method
// type has two, so we end up with
- // ByReferenceExplicitSelfCategory.
+ // ExplicitSelfCategory::ByReference.
let impl_modifiers = count_modifiers(self_info.untransformed_self_ty);
let method_modifiers = count_modifiers(explicit_type);
method_modifiers);
let category = if impl_modifiers >= method_modifiers {
- ty::ByValueExplicitSelfCategory
+ ty::ExplicitSelfCategory::ByValue
} else {
match explicit_type.sty {
- ty::TyRef(r, mt) => ty::ByReferenceExplicitSelfCategory(*r, mt.mutbl),
- ty::TyBox(_) => ty::ByBoxExplicitSelfCategory,
- _ => ty::ByValueExplicitSelfCategory,
+ ty::TyRef(r, mt) => ty::ExplicitSelfCategory::ByReference(*r, mt.mutbl),
+ ty::TyBox(_) => ty::ExplicitSelfCategory::ByBox,
+ _ => ty::ExplicitSelfCategory::ByValue,
}
};
if !is_special_case {
return
} else {
- span_note!(tcx.sess, pat.span,
+ // Boo! Too painful to attach this to the actual warning,
+ // it should go away at some point though.
+ tcx.sess.span_note_without_error(pat.span,
"this warning will become a HARD ERROR in a future release. \
See RFC 218 for details.");
}
for &Spanned { node: ref field, span } in fields {
let field_ty = match used_fields.entry(field.name) {
Occupied(occupied) => {
- span_err!(tcx.sess, span, E0025,
- "field `{}` bound multiple times in the pattern",
- field.name);
- span_note!(tcx.sess, *occupied.get(),
- "field `{}` previously bound here",
- field.name);
+ let mut err = struct_span_err!(tcx.sess, span, E0025,
+ "field `{}` bound multiple times in the pattern",
+ field.name);
+ span_note!(&mut err, *occupied.get(),
+ "field `{}` previously bound here",
+ field.name);
+ err.emit();
tcx.types.err
}
Vacant(vacant) => {
return // not a closure method, everything is OK.
};
- span_err!(tcx.sess, span, E0174,
- "explicit use of unboxed closure method `{}` is experimental",
- method);
- fileline_help!(tcx.sess, span,
- "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
+ struct_span_err!(tcx.sess, span, E0174,
+ "explicit use of unboxed closure method `{}` is experimental",
+ method)
+ .fileline_help(span, "add `#![feature(unboxed_closures)]` to the crate \
+ attributes to enable")
+ .emit();
}
}
sig
}
_ => {
- fcx.type_error_message(call_expr.span, |actual| {
+ let mut err = fcx.type_error_struct(call_expr.span, |actual| {
format!("expected function, found `{}`", actual)
}, callee_ty, None);
if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
if pr.depth == 0 && pr.base_def != def::DefErr {
if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
- tcx.sess.span_note(span, "defined here")
+ err.span_note(span, "defined here");
}
}
}
}
+ err.emit();
+
// This is the "default" function signature, used in case of error.
// In that case, we check each argument against "error" in order to
// set up all the node type bindings.
CastError::NeedViaThinPtr |
CastError::NeedViaInt |
CastError::NeedViaUsize => {
- fcx.type_error_message(self.span, |actual| {
+ fcx.type_error_struct(self.span, |actual| {
format!("casting `{}` as `{}` is invalid",
actual,
fcx.infcx().ty_to_string(self.cast_ty))
- }, self.expr_ty, None);
- fcx.ccx.tcx.sess.fileline_help(self.span,
- &format!("cast through {} first", match e {
- CastError::NeedViaPtr => "a raw pointer",
- CastError::NeedViaThinPtr => "a thin pointer",
- CastError::NeedViaInt => "an integer",
- CastError::NeedViaUsize => "a usize",
- _ => unreachable!()
- }));
+ }, self.expr_ty, None)
+ .fileline_help(self.span,
+ &format!("cast through {} first", match e {
+ CastError::NeedViaPtr => "a raw pointer",
+ CastError::NeedViaThinPtr => "a thin pointer",
+ CastError::NeedViaInt => "an integer",
+ CastError::NeedViaUsize => "a usize",
+ _ => unreachable!()
+ }))
+ .emit();
}
CastError::CastToBool => {
- span_err!(fcx.tcx().sess, self.span, E0054, "cannot cast as `bool`");
- fcx.ccx.tcx.sess.fileline_help(self.span, "compare with zero instead");
+ struct_span_err!(fcx.tcx().sess, self.span, E0054, "cannot cast as `bool`")
+ .fileline_help(self.span, "compare with zero instead")
+ .emit();
}
CastError::CastToChar => {
fcx.type_error_message(self.span, |actual| {
}, self.expr_ty, None);
}
CastError::DifferingKinds => {
- fcx.type_error_message(self.span, |actual| {
+ fcx.type_error_struct(self.span, |actual| {
format!("casting `{}` as `{}` is invalid",
actual,
fcx.infcx().ty_to_string(self.cast_ty))
- }, self.expr_ty, None);
- fcx.ccx.tcx.sess.fileline_note(self.span, "vtable kinds may not match");
+ }, self.expr_ty, None)
+ .fileline_note(self.span, "vtable kinds may not match")
+ .emit();
}
}
}
// inscrutable, particularly for cases where one method has no
// self.
match (&trait_m.explicit_self, &impl_m.explicit_self) {
- (&ty::StaticExplicitSelfCategory,
- &ty::StaticExplicitSelfCategory) => {}
- (&ty::StaticExplicitSelfCategory, _) => {
+ (&ty::ExplicitSelfCategory::Static,
+ &ty::ExplicitSelfCategory::Static) => {}
+ (&ty::ExplicitSelfCategory::Static, _) => {
span_err!(tcx.sess, impl_m_span, E0185,
"method `{}` has a `{}` declaration in the impl, \
but not in the trait",
impl_m.explicit_self);
return;
}
- (_, &ty::StaticExplicitSelfCategory) => {
+ (_, &ty::ExplicitSelfCategory::Static) => {
span_err!(tcx.sess, impl_m_span, E0186,
"method `{}` has a `{}` declaration in the trait, \
but not in the impl",
if let Err(_) = infer::mk_eqty(&infcx, true, infer::TypeOrigin::Misc(drop_impl_span),
named_type, fresh_impl_self_ty) {
- span_err!(tcx.sess, drop_impl_span, E0366,
- "Implementations of Drop cannot be specialized");
let item_span = tcx.map.span(self_type_node_id);
- tcx.sess.span_note(item_span,
- "Use same sequence of generic type and region \
- parameters that is on the struct/enum definition");
+ struct_span_err!(tcx.sess, drop_impl_span, E0366,
+ "Implementations of Drop cannot be specialized")
+ .span_note(item_span,
+ "Use same sequence of generic type and region \
+ parameters that is on the struct/enum definition")
+ .emit();
return Err(());
}
if !assumptions_in_impl_context.contains(&predicate) {
let item_span = tcx.map.span(self_type_node_id);
- span_err!(tcx.sess, drop_impl_span, E0367,
- "The requirement `{}` is added only by the Drop impl.", predicate);
- tcx.sess.span_note(item_span,
- "The same requirement must be part of \
- the struct/enum definition");
+ struct_span_err!(tcx.sess, drop_impl_span, E0367,
+ "The requirement `{}` is added only by the Drop impl.", predicate)
+ .span_note(item_span,
+ "The same requirement must be part of \
+ the struct/enum definition")
+ .emit();
}
}
Ok(()) => {}
Err(Error::Overflow(ref ctxt, ref detected_on_typ)) => {
let tcx = rcx.tcx();
- span_err!(tcx.sess, span, E0320,
- "overflow while adding drop-check rules for {}", typ);
+ let mut err = struct_span_err!(tcx.sess, span, E0320,
+ "overflow while adding drop-check rules for {}", typ);
match *ctxt {
TypeContext::Root => {
// no need for an additional note if the overflow
format!("`{}`", field)
};
span_note!(
- rcx.tcx().sess,
+ &mut err,
span,
"overflowed on {} field {} type: {}",
variant_name,
detected_on_typ);
}
}
+ err.emit();
}
}
}
method_ty.explicit_self);
match method_ty.explicit_self {
- ty::ByValueExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::ByValue => {
// Trait method is fn(self), no transformation needed.
assert!(!unsize);
fcx.write_autoderef_adjustment(self_expr.id, autoderefs);
}
- ty::ByReferenceExplicitSelfCategory(..) => {
+ ty::ExplicitSelfCategory::ByReference(..) => {
// Trait method is fn(&self) or fn(&mut self), need an
// autoref. Pull the region etc out of the type of first argument.
match transformed_self_ty.sty {
match *item {
ty::ImplOrTraitItem::MethodTraitItem(ref method) =>
match method.explicit_self {
- ty::StaticExplicitSelfCategory => self.mode == Mode::Path,
- ty::ByValueExplicitSelfCategory |
- ty::ByReferenceExplicitSelfCategory(..) |
- ty::ByBoxExplicitSelfCategory => true,
+ ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
+ ty::ExplicitSelfCategory::ByValue |
+ ty::ExplicitSelfCategory::ByReference(..) |
+ ty::ExplicitSelfCategory::ByBox => true,
},
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
_ => false,
use syntax::ast;
use syntax::codemap::Span;
+use syntax::errors::DiagnosticBuilder;
use rustc_front::print::pprust;
use rustc_front::hir;
mode }) => {
let cx = fcx.tcx();
- fcx.type_error_message(
+ let mut err = fcx.type_error_struct(
span,
|actual| {
format!("no {} named `{}` found for type `{}` \
// snippet
};
- let span_stored_function = || {
- cx.sess.span_note(span,
+ macro_rules! span_stored_function {
+ () => {
+ err.span_note(span,
&format!("use `({0}.{1})(...)` if you meant to call \
the function stored in the `{1}` field",
expr_string, item_name));
- };
+ }
+ }
- let span_did_you_mean = || {
- cx.sess.span_note(span, &format!("did you mean to write `{0}.{1}`?",
+ macro_rules! span_did_you_mean {
+ () => {
+ err.span_note(span, &format!("did you mean to write `{0}.{1}`?",
expr_string, item_name));
- };
+ }
+ }
// Determine if the field can be used as a function in some way
let field_ty = field.ty(cx, substs);
match field_ty.sty {
// Not all of these (e.g. unsafe fns) implement FnOnce
// so we look for these beforehand
- ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(),
+ ty::TyClosure(..) | ty::TyBareFn(..) => {
+ span_stored_function!();
+ }
// If it's not a simple function, look for things which implement FnOnce
_ => {
if let Ok(fn_once_trait_did) =
cx.lang_items.require(FnOnceTraitLangItem) {
let infcx = fcx.infcx();
infcx.probe(|_| {
- let fn_once_substs = Substs::new_trait(vec![
- infcx.next_ty_var()],
- Vec::new(),
- field_ty);
- let trait_ref = ty::TraitRef::new(fn_once_trait_did,
- cx.mk_substs(fn_once_substs));
+ let fn_once_substs =
+ Substs::new_trait(vec![infcx.next_ty_var()],
+ Vec::new(),
+ field_ty);
+ let trait_ref =
+ ty::TraitRef::new(fn_once_trait_did,
+ cx.mk_substs(fn_once_substs));
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation = Obligation::misc(span,
fcx.body_id,
let mut selcx = SelectionContext::new(infcx);
if selcx.evaluate_obligation(&obligation) {
- span_stored_function();
+ span_stored_function!();
} else {
- span_did_you_mean();
+ span_did_you_mean!();
}
});
} else {
- span_did_you_mean()
+ span_did_you_mean!();
}
}
}
}
if !static_sources.is_empty() {
- cx.sess.fileline_note(
+ err.fileline_note(
span,
"found defined static methods, maybe a `self` is missing?");
- report_candidates(fcx, span, item_name, static_sources);
+ report_candidates(fcx, &mut err, span, item_name, static_sources);
}
if !unsatisfied_predicates.is_empty() {
p))
.collect::<Vec<_>>()
.join(", ");
- cx.sess.fileline_note(
+ err.fileline_note(
span,
&format!("the method `{}` exists but the \
following trait bounds were not satisfied: {}",
bound_list));
}
- suggest_traits_to_import(fcx, span, rcvr_ty, item_name,
- rcvr_expr, out_of_scope_traits)
+ suggest_traits_to_import(fcx, &mut err, span, rcvr_ty, item_name,
+ rcvr_expr, out_of_scope_traits);
+ err.emit();
}
MethodError::Ambiguity(sources) => {
- span_err!(fcx.sess(), span, E0034,
- "multiple applicable items in scope");
+ let mut err = struct_span_err!(fcx.sess(), span, E0034,
+ "multiple applicable items in scope");
- report_candidates(fcx, span, item_name, sources);
+ report_candidates(fcx, &mut err, span, item_name, sources);
+ err.emit();
}
MethodError::ClosureAmbiguity(trait_def_id) => {
}
fn report_candidates(fcx: &FnCtxt,
+ err: &mut DiagnosticBuilder,
span: Span,
item_name: ast::Name,
mut sources: Vec<CandidateSource>) {
}
};
- span_note!(fcx.sess(), item_span,
+ span_note!(err, item_span,
"candidate #{} is defined in an impl{} for the type `{}`",
idx + 1,
insertion,
CandidateSource::TraitSource(trait_did) => {
let item = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
let item_span = fcx.tcx().map.def_id_span(item.def_id(), span);
- span_note!(fcx.sess(), item_span,
+ span_note!(err, item_span,
"candidate #{} is defined in the trait `{}`",
idx + 1,
fcx.tcx().item_path_str(trait_did));
pub type AllTraitsVec = Vec<TraitInfo>;
fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ err: &mut DiagnosticBuilder,
span: Span,
rcvr_ty: Ty<'tcx>,
item_name: ast::Name,
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
- fcx.sess().fileline_help(span, &msg[..]);
+ err.fileline_help(span, &msg[..]);
for (i, trait_did) in candidates.iter().enumerate() {
- fcx.sess().fileline_help(span,
- &*format!("candidate #{}: use `{}`",
- i + 1,
- fcx.tcx().item_path_str(*trait_did)))
-
+ err.fileline_help(span,
+ &*format!("candidate #{}: use `{}`",
+ i + 1,
+ fcx.tcx().item_path_str(*trait_did)));
}
return
}
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
name = item_name);
- fcx.sess().fileline_help(span, &msg[..]);
+ err.fileline_help(span, &msg[..]);
for (i, trait_info) in candidates.iter().enumerate() {
- fcx.sess().fileline_help(span,
- &*format!("candidate #{}: `{}`",
- i + 1,
- fcx.tcx().item_path_str(trait_info.def_id)))
+ err.fileline_help(span,
+ &*format!("candidate #{}: `{}`",
+ i + 1,
+ fcx.tcx().item_path_str(trait_info.def_id)));
}
}
}
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{self, Span, Spanned};
+use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::{self, InternedString};
use syntax::ptr::P;
use syntax::util::lev_distance::find_best_match_for_name;
for item in &m.items {
let pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(item.id));
if !pty.generics.types.is_empty() {
- span_err!(ccx.tcx.sess, item.span, E0044,
+ let mut err = struct_span_err!(ccx.tcx.sess, item.span, E0044,
"foreign items may not have type parameters");
- span_help!(ccx.tcx.sess, item.span,
+ span_help!(&mut err, item.span,
"consider using specialization instead of \
type parameters");
+ err.emit();
}
if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
t_expr: Ty<'tcx>,
id: ast::NodeId) {
let tstr = fcx.infcx().ty_to_string(t_cast);
- fcx.type_error_message(span, |actual| {
+ let mut err = fcx.type_error_struct(span, |actual| {
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
}, t_expr, None);
match t_expr.sty {
if t_cast.is_trait() {
match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
Ok(s) => {
- fcx.tcx().sess.span_suggestion(t_span,
- "try casting to a reference instead:",
- format!("&{}{}", mtstr, s));
+ err.span_suggestion(t_span,
+ "try casting to a reference instead:",
+ format!("&{}{}", mtstr, s));
},
Err(_) =>
- span_help!(fcx.tcx().sess, t_span,
+ span_help!(err, t_span,
"did you mean `&{}{}`?", mtstr, tstr),
}
} else {
- span_help!(fcx.tcx().sess, span,
+ span_help!(err, span,
"consider using an implicit coercion to `&{}{}` instead",
mtstr, tstr);
}
ty::TyBox(..) => {
match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
Ok(s) => {
- fcx.tcx().sess.span_suggestion(t_span,
- "try casting to a `Box` instead:",
- format!("Box<{}>", s));
+ err.span_suggestion(t_span,
+ "try casting to a `Box` instead:",
+ format!("Box<{}>", s));
},
Err(_) =>
- span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
+ span_help!(err, t_span, "did you mean `Box<{}>`?", tstr),
}
}
_ => {
- span_help!(fcx.tcx().sess, e_span,
+ span_help!(err, e_span,
"consider using a box or reference as appropriate");
}
}
+ err.emit();
fcx.write_error(id);
}
Some((adt, variant))
} else if var_kind == ty::VariantKind::Unit {
if !self.tcx().sess.features.borrow().braced_empty_structs {
- self.tcx().sess.span_err(span, "empty structs and enum variants \
- with braces are unstable");
- fileline_help!(self.tcx().sess, span, "add #![feature(braced_empty_structs)] to \
- the crate features to enable");
+ let mut err = self.tcx().sess.struct_span_err(span,
+ "empty structs and enum variants \
+ with braces are unstable");
+ fileline_help!(&mut err, span, "add #![feature(braced_empty_structs)] to \
+ the crate features to enable");
+ err.emit();
}
Some((adt, variant))
sp: Span,
mk_msg: M,
actual_ty: Ty<'tcx>,
- err: Option<&TypeError<'tcx>>) where
- M: FnOnce(String) -> String,
+ err: Option<&TypeError<'tcx>>)
+ where M: FnOnce(String) -> String,
{
self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
}
+ pub fn type_error_struct<M>(&self,
+ sp: Span,
+ mk_msg: M,
+ actual_ty: Ty<'tcx>,
+ err: Option<&TypeError<'tcx>>)
+ -> DiagnosticBuilder<'tcx>
+ where M: FnOnce(String) -> String,
+ {
+ self.infcx().type_error_struct(sp, mk_msg, actual_ty, err)
+ }
+
pub fn report_mismatched_types(&self,
sp: Span,
e: Ty<'tcx>,
lvalue_pref: LvaluePreference,
base: &'tcx hir::Expr,
field: &Spanned<ast::Name>) {
- let tcx = fcx.ccx.tcx;
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
let expr_t = structurally_resolved_type(fcx, expr.span,
fcx.expr_ty(base));
}
if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
- fcx.type_error_message(
- field.span,
- |actual| {
- format!("attempted to take value of method `{}` on type \
- `{}`", field.node, actual)
- },
- expr_t, None);
-
- tcx.sess.fileline_help(field.span,
+ fcx.type_error_struct(field.span,
+ |actual| {
+ format!("attempted to take value of method `{}` on type \
+ `{}`", field.node, actual)
+ },
+ expr_t, None)
+ .fileline_help(field.span,
"maybe a `()` to call it is missing? \
- If not, try an anonymous function");
+ If not, try an anonymous function")
+ .emit();
} else {
- fcx.type_error_message(
+ let mut err = fcx.type_error_struct(
expr.span,
|actual| {
format!("attempted access of field `{}` on \
},
expr_t, None);
if let ty::TyStruct(def, _) = expr_t.sty {
- suggest_field_names(def.struct_variant(), field, tcx, vec![]);
+ suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
}
+ err.emit();
}
fcx.write_error(expr.id);
}
// displays hints about the closest matches in field names
- fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
+ fn suggest_field_names<'tcx>(err: &mut DiagnosticBuilder,
+ variant: ty::VariantDef<'tcx>,
field: &Spanned<ast::Name>,
- tcx: &ty::ctxt<'tcx>,
skip : Vec<InternedString>) {
let name = field.node.as_str();
let names = variant.fields
// only find fits with at least one matching letter
if let Some(name) = find_best_match_for_name(names, &name, Some(name.len())) {
- tcx.sess.span_help(field.span,
- &format!("did you mean `{}`?", name));
+ err.span_help(field.span,
+ &format!("did you mean `{}`?", name));
}
}
variant: ty::VariantDef<'tcx>,
field: &hir::Field,
skip_fields: &[hir::Field]) {
- fcx.type_error_message(
+ let mut err = fcx.type_error_struct(
field.name.span,
|actual| if let ty::TyEnum(..) = ty.sty {
format!("struct variant `{}::{}` has no field named `{}`",
None);
// prevent all specified fields from being suggested
let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
- suggest_field_names(variant, &field.name, fcx.tcx(), skip_fields.collect());
+ suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
+ err.emit();
}
fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// caught by case 1.
match rty.is_representable(tcx, sp) {
Representability::SelfRecursive => {
- span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
- tcx.sess.fileline_help(
- sp, "wrap the inner value in a box to make it representable");
+ struct_span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation)
+ .fileline_help(sp, "wrap the inner value in a box to make it representable")
+ .emit();
return false
}
Representability::Representable | Representability::ContainsRecursive => (),
// Check for duplicate discriminant values
match disr_vals.iter().position(|&x| x == current_disr_val) {
Some(i) => {
- span_err!(ccx.tcx.sess, v.span, E0081,
+ let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0081,
"discriminant value `{}` already exists", disr_vals[i]);
let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
- span_note!(ccx.tcx.sess, ccx.tcx.map.span(variant_i_node_id),
- "conflicting discriminant here")
+ span_note!(&mut err, ccx.tcx.map.span(variant_i_node_id),
+ "conflicting discriminant here");
+ err.emit();
}
None => {}
}
attr::ReprAny | attr::ReprExtern => (),
attr::ReprInt(sp, ity) => {
if !disr_in_range(ccx, ity, current_disr_val) {
- span_err!(ccx.tcx.sess, v.span, E0082,
+ let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0082,
"discriminant value outside specified type");
- span_note!(ccx.tcx.sess, sp,
+ span_note!(&mut err, sp,
"discriminant type specified here");
+ err.emit();
}
}
attr::ReprSimd => {
hir_util::binop_to_string(op.node),
lhs_ty);
} else {
- span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
- "binary operation `{}` cannot be applied to type `{}`",
- hir_util::binop_to_string(op.node),
- lhs_ty);
+ let mut err = struct_span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
+ "binary operation `{}` cannot be applied to type `{}`",
+ hir_util::binop_to_string(op.node),
+ lhs_ty);
let missing_trait = match op.node {
hir::BiAdd => Some("std::ops::Add"),
hir::BiSub => Some("std::ops::Sub"),
};
if let Some(missing_trait) = missing_trait {
- span_note!(fcx.tcx().sess, lhs_expr.span,
+ span_note!(&mut err, lhs_expr.span,
"an implementation of `{}` might be missing for `{}`",
missing_trait, lhs_ty);
}
+ err.emit();
}
}
fcx.tcx().types.err
use std::collections::HashSet;
use syntax::ast;
use syntax::codemap::{Span};
+use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::{special_idents};
use rustc_front::intravisit::{self, Visitor};
use rustc_front::hir;
method.name, method.explicit_self, self_ty, sig);
let rcvr_ty = match method.explicit_self {
- ty::StaticExplicitSelfCategory => return,
- ty::ByValueExplicitSelfCategory => self_ty,
- ty::ByReferenceExplicitSelfCategory(region, mutability) => {
+ ty::ExplicitSelfCategory::Static => return,
+ ty::ExplicitSelfCategory::ByValue => self_ty,
+ ty::ExplicitSelfCategory::ByReference(region, mutability) => {
fcx.tcx().mk_ref(fcx.tcx().mk_region(region), ty::TypeAndMut {
ty: self_ty,
mutbl: mutability
})
}
- ty::ByBoxExplicitSelfCategory => fcx.tcx().mk_box(self_ty)
+ ty::ExplicitSelfCategory::ByBox => fcx.tcx().mk_box(self_ty)
};
let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
let rcvr_ty = fcx.tcx().liberate_late_bound_regions(free_id_outlive,
span: Span,
param_name: ast::Name)
{
- error_392(self.tcx(), span, param_name);
+ let mut err = error_392(self.tcx(), span, param_name);
let suggested_marker_id = self.tcx().lang_items.phantom_data();
match suggested_marker_id {
Some(def_id) => {
- self.tcx().sess.fileline_help(
+ err.fileline_help(
span,
&format!("consider removing `{}` or using a marker such as `{}`",
param_name,
// no lang items, no help!
}
}
+ err.emit();
}
}
Trait for ..`) must have no methods or associated items")
}
-pub fn error_392<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, param_name: ast::Name) {
- span_err!(tcx.sess, span, E0392,
- "parameter `{}` is never used", param_name);
+pub fn error_392<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, param_name: ast::Name)
+ -> DiagnosticBuilder<'tcx> {
+ struct_span_err!(tcx.sess, span, E0392,
+ "parameter `{}` is never used", param_name)
}
pub fn error_194<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, name: ast::Name) {
!self.fcx.expr_ty(lhs).references_error() &&
!self.fcx.expr_ty(rhs).references_error()
{
- tcx.sess.span_err(
- e.span,
- "overloaded augmented assignments are not stable");
- fileline_help!(
- tcx.sess, e.span,
- "add #![feature(augmented_assignments)] to the crate root \
- to enable");
+ tcx.sess.struct_span_err(e.span,
+ "overloaded augmented assignments \
+ are not stable")
+ .fileline_help(e.span,
+ "add #![feature(augmented_assignments)] to the \
+ crate root to enable")
+ .emit()
}
}
}
} else {
return // everything OK
};
- span_err!(tcx.sess, sp, E0183, "manual implementations of `{}` are experimental", trait_name);
- fileline_help!(tcx.sess, sp,
- "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
+ let mut err = struct_span_err!(tcx.sess,
+ sp,
+ E0183,
+ "manual implementations of `{}` are experimental",
+ trait_name);
+ fileline_help!(&mut err, sp,
+ "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
+ err.emit();
}
pub fn check_coherence(crate_context: &CrateCtxt) {
match lang_def_id {
Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ },
_ => {
- span_err!(self.tcx.sess, span, E0390,
+ struct_span_err!(self.tcx.sess, span, E0390,
"only a single inherent implementation marked with `#[lang = \"{}\"]` \
- is allowed for the `{}` primitive", lang, ty);
- span_help!(self.tcx.sess, span,
- "consider using a trait to implement these methods");
+ is allowed for the `{}` primitive", lang, ty)
+ .span_help(span, "consider using a trait to implement these methods")
+ .emit();
}
}
}
}).unwrap_or(String::new())
};
- span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119,
- "conflicting implementations of trait `{}`{}:",
- trait_ref,
- self_type);
+ let mut err = struct_span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119,
+ "conflicting implementations of trait `{}`{}:",
+ trait_ref,
+ self_type);
if impl2.is_local() {
- span_note!(self.tcx.sess, self.span_of_impl(impl2),
+ span_note!(&mut err, self.span_of_impl(impl2),
"conflicting implementation is here:");
} else {
let cname = self.tcx.sess.cstore.crate_name(impl2.krate);
- self.tcx.sess.note(&format!("conflicting implementation in crate `{}`", cname));
+ err.note(&format!("conflicting implementation in crate `{}`", cname));
}
+ err.emit();
}
fn span_of_impl(&self, impl_did: DefId) -> Span {
assert!(!cycle.is_empty());
let tcx = self.tcx;
- span_err!(tcx.sess, span, E0391,
+ let mut err = struct_span_err!(tcx.sess, span, E0391,
"unsupported cyclic reference between types/traits detected");
match cycle[0] {
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("the cycle begins when processing `{}`...",
tcx.item_path_str(def_id)));
}
AstConvRequest::EnsureSuperPredicates(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("the cycle begins when computing the supertraits of `{}`...",
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
- tcx.sess.note(
+ err.note(
&format!("the cycle begins when computing the bounds \
for type parameter `{}`...",
def.name));
match *request {
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("...which then requires processing `{}`...",
tcx.item_path_str(def_id)));
}
AstConvRequest::EnsureSuperPredicates(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("...which then requires computing the supertraits of `{}`...",
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
- tcx.sess.note(
+ err.note(
&format!("...which then requires computing the bounds \
for type parameter `{}`...",
def.name));
match cycle[0] {
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("...which then again requires processing `{}`, completing the cycle.",
tcx.item_path_str(def_id)));
}
AstConvRequest::EnsureSuperPredicates(def_id) => {
- tcx.sess.note(
+ err.note(
&format!("...which then again requires computing the supertraits of `{}`, \
completing the cycle.",
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
- tcx.sess.note(
+ err.note(
&format!("...which then again requires computing the bounds \
for type parameter `{}`, completing the cycle.",
def.name));
}
}
+ err.emit();
}
/// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
hir::NamedField(name, vis) => {
let dup_span = seen_fields.get(&name).cloned();
if let Some(prev_span) = dup_span {
- span_err!(tcx.sess, f.span, E0124,
- "field `{}` is already declared",
- name);
- span_note!(tcx.sess, prev_span, "previously declared here");
+ let mut err = struct_span_err!(tcx.sess, f.span, E0124,
+ "field `{}` is already declared",
+ name);
+ span_note!(&mut err, prev_span, "previously declared here");
+ err.emit();
} else {
seen_fields.insert(name, f.span);
}
None
},
Err(err) => {
- span_err!(tcx.sess, err.span, E0080,
- "constant evaluation error: {}",
- err.description());
+ let mut diag = struct_span_err!(tcx.sess, err.span, E0080,
+ "constant evaluation error: {}",
+ err.description());
if !e.span.contains(err.span) {
- tcx.sess.span_note(e.span, "for enum discriminant here");
+ diag.span_note(e.span, "for enum discriminant here");
}
+ diag.emit();
None
}
}
let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
- ccx.tcx.sess.span_err(
+ let mut err = ccx.tcx.sess.struct_span_err(
it.span,
"the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
which traits can use parenthetical notation");
- fileline_help!(ccx.tcx.sess, it.span,
+ fileline_help!(&mut err, it.span,
"add `#![feature(unboxed_closures)]` to \
the crate attributes to use it");
+ err.emit();
}
let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
match result {
Ok(_) => true,
Err(ref terr) => {
- span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
- tcx.note_and_explain_type_err(terr, span);
+ let mut err = struct_span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
+ tcx.note_and_explain_type_err(&mut err, terr, span);
+ err.emit();
false
}
}
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
fn clean(&self, cx: &DocContext) -> Item {
let (self_, sig) = match self.explicit_self {
- ty::StaticExplicitSelfCategory => (hir::SelfStatic.clean(cx),
- self.fty.sig.clone()),
+ ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx),
+ self.fty.sig.clone()),
s => {
let sig = ty::Binder(ty::FnSig {
inputs: self.fty.sig.0.inputs[1..].to_vec(),
..self.fty.sig.0.clone()
});
let s = match s {
- ty::ByValueExplicitSelfCategory => SelfValue,
- ty::ByReferenceExplicitSelfCategory(..) => {
+ ty::ExplicitSelfCategory::ByValue => SelfValue,
+ ty::ExplicitSelfCategory::ByReference(..) => {
match self.fty.sig.0.inputs[0].sty {
ty::TyRef(r, mt) => {
SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
_ => unreachable!(),
}
}
- ty::ByBoxExplicitSelfCategory => {
+ ty::ExplicitSelfCategory::ByBox => {
SelfExplicit(self.fty.sig.0.inputs[0].clean(cx))
}
- ty::StaticExplicitSelfCategory => unreachable!(),
+ ty::ExplicitSelfCategory::Static => unreachable!(),
};
(s, sig)
}
#[cfg_attr(any(windows,
target_os = "android", // FIXME #10379
target_env = "musl"), ignore)]
+ #[allow(deprecated)]
fn test_loading_cosine() {
// The math library does not need to be loaded since it is already
// statically linked in
target_os = "bitrig",
target_os = "netbsd",
target_os = "openbsd"))]
+ #[allow(deprecated)]
fn test_errors_do_not_crash() {
// Open /dev/null as a library to get an error, and make sure
// that only causes an error, and not a crash.
use io::{ErrorKind, SeekFrom};
use path::PathBuf;
use path::Path as Path2;
- use os;
use rand::{self, StdRng, Rng};
use str;
let message = "ten-four";
let mut read_mem = [0; 4];
let set_cursor = 4 as u64;
- let mut tell_pos_pre_read;
- let mut tell_pos_post_read;
+ let tell_pos_pre_read;
+ let tell_pos_post_read;
let tmpdir = tmpdir();
let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
{
mod tests {
use prelude::v1::*;
use io::prelude::*;
- use io::{self, BufReader, BufWriter, Cursor, LineWriter, SeekFrom};
+ use io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
use test;
/// A dummy reader intended at testing short-reads propagation.
struct TestError;
impl fmt::Display for TestError {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
b.iter(|| {
let mut lr = repeat(1).take(10000000);
let mut vec = Vec::with_capacity(1024);
- super::read_to_end(&mut lr, &mut vec);
+ super::read_to_end(&mut lr, &mut vec)
});
}
}
/// A handle to the standard input stream of a process.
///
/// Each handle is a shared reference to a global buffer of input data to this
-/// process. A handle can be `lock`'d to gain full access to `BufRead` methods
+/// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods
/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
/// to other writes.
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
///
-/// Created by the function `io::stdin()`.
+/// Created by the [`io::stdin`] method.
+///
+/// [`io::stdin`]: fn.stdin.html
+/// [`BufRead`]: trait.BufRead.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
/// A locked reference to the `Stdin` handle.
///
-/// This handle implements both the `Read` and `BufRead` traits and is
-/// constructed via the `lock` method on `Stdin`.
+/// This handle implements both the [`Read`] and [`BufRead`] traits, and
+/// is constructed via the [`Stdin::lock`] method.
+///
+/// [`Read`]: trait.Read.html
+/// [`BufRead`]: trait.BufRead.html
+/// [`Stdin::lock`]: struct.Stdin.html#method.lock
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. If you need more explicit control over
-/// locking, see the [lock() method][lock].
+/// locking, see the [`lock() method`][lock].
///
/// [lock]: struct.Stdin.html#method.lock
///
/// guard.
///
/// The lock is released when the returned lock goes out of scope. The
- /// returned guard also implements the `Read` and `BufRead` traits for
+ /// returned guard also implements the [`Read`] and [`BufRead`] traits for
/// accessing the underlying data.
+ ///
+ /// [Read]: trait.Read.html
+ /// [BufRead]: trait.BufRead.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdinLock {
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
/// Locks this handle and reads a line of input into the specified buffer.
///
/// For detailed semantics of this method, see the documentation on
- /// `BufRead::read_line`.
+ /// [`BufRead::read_line`].
+ ///
+ /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
///
/// # Examples
///
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
///
-/// Created by the function `io::stdout()`.
+/// Created by the [`io::stdout`] method.
+///
+/// [`io::stdout`]: fn.stdout.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
/// A locked reference to the `Stdout` handle.
///
-/// This handle implements the `Write` trait and is constructed via the `lock`
-/// method on `Stdout`.
+/// This handle implements the [`Write`] trait, and is constructed via
+/// the [`Stdout::lock`] method.
+///
+/// [`Write`]: trait.Write.html
+/// [`Stdout::lock`]: struct.Stdout.html#method.lock
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. If you need more explicit control over
-/// locking, see the [lock() method][lock].
+/// locking, see the [Stdout::lock] method.
///
-/// [lock]: struct.Stdout.html#method.lock
+/// [Stdout::lock]: struct.Stdout.html#method.lock
///
/// # Examples
///
/// A handle to the standard error stream of a process.
///
-/// For more information, see `stderr`
+/// For more information, see the [`io::stderr`] method.
+///
+/// [`io::stderr`]: fn.stderr.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
/// A locked reference to the `Stderr` handle.
///
-/// This handle implements the `Write` trait and is constructed via the `lock`
-/// method on `Stderr`.
+/// This handle implements the `Write` trait and is constructed via
+/// the [`Stderr::lock`] method.
+///
+/// [`Stderr::lock`]: struct.Stderr.html#method.lock
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
}
#[test]
+ #[allow(deprecated)]
fn tee() {
let mut buf = [0; 10];
{
}
#[test]
+ #[allow(deprecated)]
fn broadcast() {
let mut buf1 = [0; 10];
let mut buf2 = [0; 10];
#[cfg(test)]
mod tests {
use prelude::v1::*;
- use io;
use net::*;
- use net::Ipv6MulticastScope::*;
use net::test::{tsa, sa6, sa4};
#[test]
#[cfg(test)]
mod tests {
use prelude::v1::*;
- use io;
use net::*;
use net::Ipv6MulticastScope::*;
use net::test::{tsa, sa6, sa4};
use net::test::{next_test_ip4, next_test_ip6};
use sync::mpsc::channel;
use sys_common::AsInner;
- use time::Duration;
+ use time::{Instant, Duration};
use thread;
fn each_ip(f: &mut FnMut(SocketAddr)) {
t!(stream.set_write_timeout(None));
assert_eq!(None, t!(stream.write_timeout()));
+ drop(listener);
}
#[test]
t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
let mut buf = [0; 10];
- let wait = Duration::span(|| {
- let kind = stream.read(&mut buf).err().expect("expected error").kind();
- assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
- });
- assert!(wait > Duration::from_millis(400));
+ let start = Instant::now();
+ let kind = stream.read(&mut buf).err().expect("expected error").kind();
+ assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+ assert!(start.elapsed() > Duration::from_millis(400));
+ drop(listener);
}
#[test]
t!(stream.read(&mut buf));
assert_eq!(b"hello world", &buf[..]);
- let wait = Duration::span(|| {
- let kind = stream.read(&mut buf).err().expect("expected error").kind();
- assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
- });
- assert!(wait > Duration::from_millis(400));
+ let start = Instant::now();
+ let kind = stream.read(&mut buf).err().expect("expected error").kind();
+ assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+ assert!(start.elapsed() > Duration::from_millis(400));
+ drop(listener);
}
}
/// use std::net::UdpSocket;
///
/// # fn foo() -> std::io::Result<()> {
-/// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254"));
+/// {
+/// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254"));
///
-/// let mut buf = [0; 10];
-/// let (amt, src) = try!(socket.recv_from(&mut buf));
+/// // read from the socket
+/// let mut buf = [0; 10];
+/// let (amt, src) = try!(socket.recv_from(&mut buf));
///
-/// // Send a reply to the socket we received data from
-/// let buf = &mut buf[..amt];
-/// buf.reverse();
-/// try!(socket.send_to(buf, &src));
-///
-/// drop(socket); // close the socket
-/// # Ok(())
+/// // send a reply to the socket we received data from
+/// let buf = &mut buf[..amt];
+/// buf.reverse();
+/// try!(socket.send_to(buf, &src));
+/// # Ok(())
+/// } // the socket is closed here
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
use net::test::{next_test_ip4, next_test_ip6};
use sync::mpsc::channel;
use sys_common::AsInner;
- use time::Duration;
+ use time::{Instant, Duration};
use thread;
fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
fn test_read_timeout() {
let addr = next_test_ip4();
- let mut stream = t!(UdpSocket::bind(&addr));
+ let stream = t!(UdpSocket::bind(&addr));
t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
let mut buf = [0; 10];
- let wait = Duration::span(|| {
- let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
- assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
- });
- assert!(wait > Duration::from_millis(400));
+
+ let start = Instant::now();
+ let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+ assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+ assert!(start.elapsed() > Duration::from_millis(400));
}
#[test]
fn test_read_with_timeout() {
let addr = next_test_ip4();
- let mut stream = t!(UdpSocket::bind(&addr));
+ let stream = t!(UdpSocket::bind(&addr));
t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
t!(stream.send_to(b"hello world", &addr));
t!(stream.recv_from(&mut buf));
assert_eq!(b"hello world", &buf[..]);
- let wait = Duration::span(|| {
- let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
- assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
- });
- assert!(wait > Duration::from_millis(400));
+ let start = Instant::now();
+ let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
+ assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
+ assert!(start.elapsed() > Duration::from_millis(400));
}
}
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
+#[cfg(not(test))]
use core::num;
+#[cfg(not(test))]
use intrinsics;
+#[cfg(not(test))]
use libc::c_int;
+#[cfg(not(test))]
use num::FpCategory;
+
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[stable(feature = "rust1", since = "1.0.0")]
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
+#[cfg(not(test))]
use core::num;
+#[cfg(not(test))]
use intrinsics;
+#[cfg(not(test))]
use libc::c_int;
+#[cfg(not(test))]
use num::FpCategory;
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(test)]
mod tests {
use super::*;
- use i8;
- use i16;
- use i32;
- use i64;
- use isize;
use u8;
use u16;
use u32;
c_longlong c_ulonglong c_float c_double);
}
- #[cfg(unix)]
+ #[cfg(all(unix, not(target_os = "android")))]
+ #[test]
fn unix() {
{
use os::unix::raw;
}
#[cfg(windows)]
+ #[test]
fn windows() {
use os::windows::raw;
}
#[cfg(test)]
mod tests {
- use prelude::v1::*;
-
use sync::mpsc::channel;
use rand::Rng;
use super::OsRng;
#[cfg(test)]
mod tests {
- use prelude::v1::*;
-
use super::ReaderRng;
use rand::Rng;
issue = "0")]
#![doc(hidden)]
-use borrow::ToOwned;
-use mem;
-use panic;
-use sys;
-use sys_common::thread_info::{self, NewThread};
-use sys_common;
-use thread::Thread;
+
// Reexport some of our utilities which are expected by other crates.
pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt};
#[cfg(not(test))]
#[lang = "start"]
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
+ use borrow::ToOwned;
+ use mem;
+ use panic;
+ use sys;
+ use sys_common;
+ use sys_common::thread_info::{self, NewThread};
+ use thread::Thread;
+
sys::init();
let failed = unsafe {
static M: StaticMutex = StaticMutex::new();
let g = M.lock().unwrap();
- let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap();
+ let (g, _no_timeout) = C.wait_timeout(g, Duration::from_millis(1)).unwrap();
// spurious wakeups mean this isn't necessarily true
// assert!(!no_timeout);
let _t = thread::spawn(move || {
let _g = M.lock().unwrap();
C.notify_one();
});
- let (g, no_timeout) = C.wait_timeout_ms(g, u32::MAX).unwrap();
- assert!(no_timeout);
+ let (g, timeout_res) = C.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap();
+ assert!(!timeout_res.timed_out());
drop(g);
unsafe { C.destroy(); M.destroy(); }
}
b.iter(|| {
let mut lr = repeat(1).take(10000000);
let mut vec = Vec::with_capacity(1024);
- unsafe { read_to_end_uninitialized(&mut lr, &mut vec) };
+ unsafe { read_to_end_uninitialized(&mut lr, &mut vec) }
});
}
}
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use cell::RefCell;
use sync::Arc;
- use boxed;
use thread;
#[test]
fn trylock_works() {
let m = Arc::new(ReentrantMutex::new(()));
let m2 = m.clone();
- let lock = m.try_lock().unwrap();
- let lock2 = m.try_lock().unwrap();
+ let _lock = m.try_lock().unwrap();
+ let _lock2 = m.try_lock().unwrap();
thread::spawn(move || {
let lock = m2.try_lock();
assert!(lock.is_err());
}).join().unwrap();
- let lock3 = m.try_lock().unwrap();
+ let _lock3 = m.try_lock().unwrap();
}
pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
*lock.borrow_mut() = 1;
let lock2 = mc.lock().unwrap();
*lock.borrow_mut() = 2;
- let answer = Answer(lock2);
+ let _answer = Answer(lock2);
panic!("What the answer to my lifetimes dilemma is?");
- drop(answer);
}).join();
assert!(result.is_err());
let r = m.lock().err().unwrap().into_inner();
#[test]
fn wtf8buf_show_str() {
let text = "a\té 💩\r";
- let mut string = Wtf8Buf::from_str(text);
+ let string = Wtf8Buf::from_str(text);
assert_eq!(format!("{:?}", text), format!("{:?}", string));
}
pub mod time;
pub mod stdio;
-#[cfg(not(target_os = "nacl"))]
+#[cfg(not(any(target_os = "nacl", test)))]
pub fn init() {
use libc::signal;
// By default, some platforms will send a *signal* when an EPIPE error
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
}
}
-#[cfg(target_os = "nacl")]
+
+#[cfg(all(target_os = "nacl", not(test)))]
pub fn init() { }
pub fn decode_error_kind(errno: i32) -> ErrorKind {
use mem;
use ptr;
use libc;
- use slice;
- use sys::{self, cvt, pipe};
+ use sys::{self, cvt};
macro_rules! t {
($e:expr) => {
#[cfg(target_os = "android")]
unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
+ use slice;
+
let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
let bit = (signum - 1) as usize;
raw[bit / 8] |= 1 << (bit % 8);
// <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.
+#![cfg_attr(test, allow(dead_code))]
use libc;
use self::imp::{make_handler, drop_handler};
-pub use self::imp::{init, cleanup};
+pub use self::imp::cleanup;
+pub use self::imp::init;
pub struct Handler {
_data: *mut libc::c_void
target_os = "openbsd"))]
mod imp {
use super::Handler;
- use sys_common::util::report_overflow;
use mem;
use ptr;
+ use libc::{sigaltstack, SIGSTKSZ};
use libc::{sigaction, SIGBUS, SIG_DFL,
- SA_SIGINFO, SA_ONSTACK, sigaltstack,
- SIGSTKSZ, sighandler_t};
+ SA_SIGINFO, SA_ONSTACK, sighandler_t};
use libc;
use libc::{mmap, munmap};
use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON};
unsafe extern fn signal_handler(signum: libc::c_int,
info: *mut libc::siginfo_t,
_data: *mut libc::c_void) {
+ use sys_common::util::report_overflow;
+
let guard = thread_info::stack_guard().unwrap_or(0);
let addr = siginfo_si_addr(info) as usize;
fn test_park_timeout_unpark_before() {
for _ in 0..10 {
thread::current().unpark();
- thread::park_timeout_ms(u32::MAX);
+ thread::park_timeout(Duration::from_millis(u32::MAX as u64));
}
}
#[test]
fn test_park_timeout_unpark_not_called() {
for _ in 0..10 {
- thread::park_timeout_ms(10);
+ thread::park_timeout(Duration::from_millis(10));
}
}
let th = thread::current();
let _guard = thread::spawn(move || {
- super::sleep_ms(50);
+ super::sleep(Duration::from_millis(50));
th.unpark();
});
- thread::park_timeout_ms(u32::MAX);
+ thread::park_timeout(Duration::from_millis(u32::MAX as u64));
}
}
#[test]
fn sleep_ms_smoke() {
- thread::sleep_ms(2);
+ thread::sleep(Duration::from_millis(2));
}
// NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
#[cfg(test)]
mod tests {
- use prelude::v1::*;
use super::Duration;
#[test]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum PathParameters {
/// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
- AngleBracketedParameters(AngleBracketedParameterData),
+ AngleBracketed(AngleBracketedParameterData),
/// The `(A,B)` and `C` in `Foo(A,B) -> C`
- ParenthesizedParameters(ParenthesizedParameterData),
+ Parenthesized(ParenthesizedParameterData),
}
impl PathParameters {
pub fn none() -> PathParameters {
- AngleBracketedParameters(AngleBracketedParameterData {
+ PathParameters::AngleBracketed(AngleBracketedParameterData {
lifetimes: Vec::new(),
types: P::empty(),
bindings: P::empty(),
pub fn is_empty(&self) -> bool {
match *self {
- AngleBracketedParameters(ref data) => data.is_empty(),
+ PathParameters::AngleBracketed(ref data) => data.is_empty(),
// Even if the user supplied no types, something like
// `X()` is equivalent to `X<(),()>`.
- ParenthesizedParameters(..) => false,
+ PathParameters::Parenthesized(..) => false,
}
}
pub fn has_lifetimes(&self) -> bool {
match *self {
- AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(),
- ParenthesizedParameters(_) => false,
+ PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(),
+ PathParameters::Parenthesized(_) => false,
}
}
pub fn has_types(&self) -> bool {
match *self {
- AngleBracketedParameters(ref data) => !data.types.is_empty(),
- ParenthesizedParameters(..) => true,
+ PathParameters::AngleBracketed(ref data) => !data.types.is_empty(),
+ PathParameters::Parenthesized(..) => true,
}
}
/// parameters in the parenthesized case.
pub fn types(&self) -> Vec<&P<Ty>> {
match *self {
- AngleBracketedParameters(ref data) => {
+ PathParameters::AngleBracketed(ref data) => {
data.types.iter().collect()
}
- ParenthesizedParameters(ref data) => {
+ PathParameters::Parenthesized(ref data) => {
data.inputs.iter()
.chain(data.output.iter())
.collect()
pub fn lifetimes(&self) -> Vec<&Lifetime> {
match *self {
- AngleBracketedParameters(ref data) => {
+ PathParameters::AngleBracketed(ref data) => {
data.lifetimes.iter().collect()
}
- ParenthesizedParameters(_) => {
+ PathParameters::Parenthesized(_) => {
Vec::new()
}
}
pub fn bindings(&self) -> Vec<&P<TypeBinding>> {
match *self {
- AngleBracketedParameters(ref data) => {
+ PathParameters::AngleBracketed(ref data) => {
data.bindings.iter().collect()
}
- ParenthesizedParameters(_) => {
+ PathParameters::Parenthesized(_) => {
Vec::new()
}
}
segments: vec!(
ast::PathSegment {
identifier: identifier,
- parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+ parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: Vec::new(),
types: P::empty(),
bindings: P::empty(),
if let s@Some(_) = attr.value_str() {
s
} else {
- diag.span_err(attr.span, "export_name attribute has invalid format");
- diag.help("use #[export_name=\"*\"]");
+ diag.struct_span_err(attr.span,
+ "export_name attribute has invalid format")
+ .help("use #[export_name=\"*\"]")
+ .emit();
None
}
} else {
})
}
+#[macro_export]
+macro_rules! span_warn {
+ ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+ __diagnostic_used!($code);
+ $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+ })
+}
+
#[macro_export]
macro_rules! span_err_or_warn {
($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
}
#[macro_export]
-macro_rules! span_warn {
+macro_rules! struct_span_fatal {
($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
__diagnostic_used!($code);
- $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+ $session.struct_span_fatal_with_code($span, &format!($($message)*), stringify!($code))
+ })
+}
+
+#[macro_export]
+macro_rules! struct_span_err {
+ ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+ __diagnostic_used!($code);
+ $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+ })
+}
+
+#[macro_export]
+macro_rules! struct_span_warn {
+ ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+ __diagnostic_used!($code);
+ $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+ })
+}
+
+#[macro_export]
+macro_rules! struct_span_err_or_warn {
+ ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+ __diagnostic_used!($code);
+ if $is_warning {
+ $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+ } else {
+ $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+ }
})
}
#[macro_export]
macro_rules! span_note {
- ($session:expr, $span:expr, $($message:tt)*) => ({
- ($session).span_note($span, &format!($($message)*))
+ ($err:expr, $span:expr, $($message:tt)*) => ({
+ ($err).span_note($span, &format!($($message)*));
})
}
#[macro_export]
macro_rules! span_help {
- ($session:expr, $span:expr, $($message:tt)*) => ({
- ($session).span_help($span, &format!($($message)*))
+ ($err:expr, $span:expr, $($message:tt)*) => ({
+ ($err).span_help($span, &format!($($message)*));
})
}
#[macro_export]
macro_rules! fileline_help {
- ($session:expr, $span:expr, $($message:tt)*) => ({
- ($session).fileline_help($span, &format!($($message)*))
+ ($err:expr, $span:expr, $($message:tt)*) => ({
+ ($err).fileline_help($span, &format!($($message)*));
})
}
match diagnostics.get_mut(&code.name) {
// Previously used errors.
Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => {
- ecx.span_warn(span, &format!(
+ ecx.struct_span_warn(span, &format!(
"diagnostic code {} already used", code
- ));
- ecx.span_note(previous_span, "previous invocation");
+ )).span_note(previous_span, "previous invocation")
+ .emit();
}
// Newly used errors.
Some(ref mut info) => {
use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span};
use diagnostics;
-use errors::{Level, RenderSpan};
+use errors::{Level, RenderSpan, DiagnosticBuilder};
use errors::RenderSpan::*;
use errors::Level::*;
pub trait Emitter {
fn emit(&mut self, span: Option<Span>, msg: &str, code: Option<&str>, lvl: Level);
fn custom_emit(&mut self, sp: RenderSpan, msg: &str, lvl: Level);
+
+ /// Emit a structured diagnostic.
+ fn emit_struct(&mut self, db: &DiagnosticBuilder) {
+ self.emit(db.span, &db.message, db.code.as_ref().map(|s| &**s), db.level);
+ for child in &db.children {
+ match child.render_span {
+ Some(ref sp) => self.custom_emit(sp.clone(), &child.message, child.level),
+ None => self.emit(child.span, &child.message, None, child.level),
+ }
+ }
+ }
}
/// maximum number of lines we will print for each error; arbitrary.
}
}
-// A basic emitter for when we don't have access to a codemap or registry. Used
-// for reporting very early errors, etc.
+/// A basic emitter for when we don't have access to a codemap or registry. Used
+/// for reporting very early errors, etc.
pub struct BasicEmitter {
dst: Destination,
}
sp: RenderSpan,
msg: &str,
lvl: Level) {
- match self.emit_(sp, msg, None, lvl) {
- Ok(()) => {}
- Err(e) => panic!("failed to print diagnostics: {:?}", e),
+ if let Err(e) = self.emit_(sp, msg, None, lvl) {
+ panic!("failed to print diagnostics: {:?}", e);
}
}
}
}
}
+/// Used for emitting structured error messages and other diagnostic information.
+#[must_use]
+pub struct DiagnosticBuilder<'a> {
+ emitter: &'a RefCell<Box<Emitter>>,
+ level: Level,
+ message: String,
+ code: Option<String>,
+ span: Option<Span>,
+ children: Vec<SubDiagnostic>,
+}
+
+/// For example a note attached to an error.
+struct SubDiagnostic {
+ level: Level,
+ message: String,
+ span: Option<Span>,
+ render_span: Option<RenderSpan>,
+}
+
+impl<'a> DiagnosticBuilder<'a> {
+ /// Emit the diagnostic.
+ pub fn emit(&mut self) {
+ if self.cancelled() {
+ return;
+ }
+
+ self.emitter.borrow_mut().emit_struct(&self);
+ self.cancel();
+
+ // if self.is_fatal() {
+ // panic!(FatalError);
+ // }
+ }
+
+ /// Cancel the diagnostic (a structured diagnostic must either be emitted or
+ /// cancelled or it will panic when dropped).
+ /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
+ /// bump the error count on the Handler and cancelling it won't undo that.
+ /// If you want to decrement the error count you should use `Handler::cancel`.
+ pub fn cancel(&mut self) {
+ self.level = Level::Cancelled;
+ }
+
+ pub fn cancelled(&self) -> bool {
+ self.level == Level::Cancelled
+ }
+
+ pub fn is_fatal(&self) -> bool {
+ self.level == Level::Fatal
+ }
+
+ pub fn note(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Note, msg, None, None);
+ self
+ }
+ pub fn span_note(&mut self ,
+ sp: Span,
+ msg: &str)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Note, msg, Some(sp), None);
+ self
+ }
+ pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Help, msg, None, None);
+ self
+ }
+ pub fn span_help(&mut self ,
+ sp: Span,
+ msg: &str)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Help, msg, Some(sp), None);
+ self
+ }
+ /// Prints out a message with a suggested edit of the code.
+ ///
+ /// See `diagnostic::RenderSpan::Suggestion` for more information.
+ pub fn span_suggestion(&mut self ,
+ sp: Span,
+ msg: &str,
+ suggestion: String)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Help, msg, Some(sp), Some(Suggestion(sp, suggestion)));
+ self
+ }
+ pub fn span_end_note(&mut self ,
+ sp: Span,
+ msg: &str)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Note, msg, Some(sp), Some(EndSpan(sp)));
+ self
+ }
+ pub fn fileline_note(&mut self ,
+ sp: Span,
+ msg: &str)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Note, msg, Some(sp), Some(FileLine(sp)));
+ self
+ }
+ pub fn fileline_help(&mut self ,
+ sp: Span,
+ msg: &str)
+ -> &mut DiagnosticBuilder<'a> {
+ self.sub(Level::Help, msg, Some(sp), Some(FileLine(sp)));
+ self
+ }
+
+ pub fn span(&mut self, sp: Span) -> &mut Self {
+ self.span = Some(sp);
+ self
+ }
+
+ pub fn code(&mut self, s: String) -> &mut Self {
+ self.code = Some(s);
+ self
+ }
+
+ /// Convenience function for internal use, clients should use one of the
+ /// struct_* methods on Handler.
+ fn new(emitter: &'a RefCell<Box<Emitter>>,
+ level: Level,
+ message: &str) -> DiagnosticBuilder<'a> {
+ DiagnosticBuilder {
+ emitter: emitter,
+ level: level,
+ message: message.to_owned(),
+ code: None,
+ span: None,
+ children: vec![],
+ }
+ }
+
+ /// Convenience function for internal use, clients should use one of the
+ /// public methods above.
+ fn sub(&mut self,
+ level: Level,
+ message: &str,
+ span: Option<Span>,
+ render_span: Option<RenderSpan>) {
+ let sub = SubDiagnostic {
+ level: level,
+ message: message.to_owned(),
+ span: span,
+ render_span: render_span,
+ };
+ self.children.push(sub);
+ }
+}
+
+impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.message.fmt(f)
+ }
+}
+
+/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
+/// we emit a bug.
+impl<'a> Drop for DiagnosticBuilder<'a> {
+ fn drop(&mut self) {
+ if !self.cancelled() {
+ self.emitter.borrow_mut().emit(None, "Error constructed but not emitted", None, Bug);
+ panic!();
+ }
+ }
+}
+
/// A handler deals with errors; certain errors
/// (fatal, bug, unimpl) may cause immediate exit,
/// others log errors for later reporting.
}
}
+ pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
+ DiagnosticBuilder::new(&self.emit, Level::Cancelled, "")
+ }
+
+ pub fn struct_span_warn<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
+ result.span(sp);
+ if !self.can_emit_warnings {
+ result.cancel();
+ }
+ result
+ }
+ pub fn struct_span_warn_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
+ result.span(sp);
+ result.code(code.to_owned());
+ if !self.can_emit_warnings {
+ result.cancel();
+ }
+ result
+ }
+ pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
+ if !self.can_emit_warnings {
+ result.cancel();
+ }
+ result
+ }
+ pub fn struct_span_err<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
+ result.span(sp);
+ result
+ }
+ pub fn struct_span_err_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
+ result.span(sp);
+ result.code(code.to_owned());
+ result
+ }
+ pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ DiagnosticBuilder::new(&self.emit, Level::Error, msg)
+ }
+ pub fn struct_span_fatal<'a>(&'a self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
+ result.span(sp);
+ result
+ }
+ pub fn struct_span_fatal_with_code<'a>(&'a self,
+ sp: Span,
+ msg: &str,
+ code: &str)
+ -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
+ result.span(sp);
+ result.code(code.to_owned());
+ result
+ }
+ pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ self.bump_err_count();
+ DiagnosticBuilder::new(&self.emit, Level::Fatal, msg)
+ }
+
+ pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
+ if err.level == Level::Error || err.level == Level::Fatal {
+ assert!(self.has_errors());
+ self.err_count.set(self.err_count.get() + 1);
+ }
+ err.cancel();
+ }
+
pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
if self.treat_err_as_bug {
self.span_bug(sp, msg);
}
self.emit(Some(sp), msg, Fatal);
+ self.bump_err_count();
return FatalError;
}
pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> FatalError {
self.span_bug(sp, msg);
}
self.emit_with_code(Some(sp), msg, code, Fatal);
+ self.bump_err_count();
return FatalError;
}
pub fn span_err(&self, sp: Span, msg: &str) {
pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) {
self.emit_with_code(Some(sp), msg, code, Warning);
}
- pub fn span_note(&self, sp: Span, msg: &str) {
- self.emit(Some(sp), msg, Note);
- }
- pub fn span_end_note(&self, sp: Span, msg: &str) {
- self.custom_emit(EndSpan(sp), msg, Note);
- }
- pub fn span_help(&self, sp: Span, msg: &str) {
- self.emit(Some(sp), msg, Help);
- }
- /// Prints out a message with a suggested edit of the code.
- ///
- /// See `diagnostic::RenderSpan::Suggestion` for more information.
- pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) {
- self.custom_emit(Suggestion(sp, suggestion), msg, Help);
- }
- pub fn fileline_note(&self, sp: Span, msg: &str) {
- self.custom_emit(FileLine(sp), msg, Note);
- }
- pub fn fileline_help(&self, sp: Span, msg: &str) {
- self.custom_emit(FileLine(sp), msg, Help);
- }
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
self.emit(Some(sp), msg, Bug);
panic!(ExplicitBug);
self.emit(Some(sp), msg, Bug);
self.bump_err_count();
}
+ pub fn span_note_without_error(&self, sp: Span, msg: &str) {
+ self.emit.borrow_mut().emit(Some(sp), msg, None, Note);
+ }
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
self.span_bug(sp, &format!("unimplemented {}", msg));
}
self.bug(msg);
}
self.emit.borrow_mut().emit(None, msg, None, Fatal);
+ self.bump_err_count();
FatalError
}
pub fn err(&self, msg: &str) {
pub fn warn(&self, msg: &str) {
self.emit.borrow_mut().emit(None, msg, None, Warning);
}
- pub fn note(&self, msg: &str) {
+ pub fn note_without_error(&self, msg: &str) {
self.emit.borrow_mut().emit(None, msg, None, Note);
}
- pub fn help(&self, msg: &str) {
- self.emit.borrow_mut().emit(None, msg, None, Help);
- }
pub fn bug(&self, msg: &str) -> ! {
self.emit.borrow_mut().emit(None, msg, None, Bug);
panic!(ExplicitBug);
}
}
- panic!(self.fatal(&s[..]));
+ panic!(self.fatal(&s));
}
pub fn emit(&self,
Warning,
Note,
Help,
+ Cancelled,
}
impl fmt::Display for Level {
Warning => "warning".fmt(f),
Note => "note".fmt(f),
Help => "help".fmt(f),
+ Cancelled => unreachable!(),
}
}
}
Warning => term::color::BRIGHT_YELLOW,
Note => term::color::BRIGHT_GREEN,
Help => term::color::BRIGHT_CYAN,
+ Cancelled => unreachable!(),
}
}
}
use ast::Name;
use codemap;
use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
+use errors::DiagnosticBuilder;
use ext;
use ext::expand;
use ext::tt::macro_rules;
}
}
+ pub fn struct_span_warn(&self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
+ }
+ pub fn struct_span_err(&self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
+ }
+ pub fn struct_span_fatal(&self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'a> {
+ self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
+ }
+
/// Emit `msg` attached to `sp`, and stop compilation immediately.
///
/// `span_err` should be strongly preferred where-ever possible:
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
self.parse_sess.span_diagnostic.span_bug(sp, msg);
}
- pub fn span_note(&self, sp: Span, msg: &str) {
- self.parse_sess.span_diagnostic.span_note(sp, msg);
- }
- pub fn span_help(&self, sp: Span, msg: &str) {
- self.parse_sess.span_diagnostic.span_help(sp, msg);
- }
- pub fn fileline_help(&self, sp: Span, msg: &str) {
- self.parse_sess.span_diagnostic.fileline_help(sp, msg);
- }
pub fn bug(&self, msg: &str) -> ! {
self.parse_sess.span_diagnostic.bug(msg);
}
token::intern(st)
}
- pub fn suggest_macro_name(&mut self, name: &str, span: Span) {
+ pub fn suggest_macro_name(&mut self,
+ name: &str,
+ span: Span,
+ err: &mut DiagnosticBuilder<'a>) {
let names = &self.syntax_env.names;
if let Some(suggestion) = find_best_match_for_name(names.iter(), name, None) {
- self.fileline_help(span, &format!("did you mean `{}!`?", suggestion));
+ err.fileline_help(span, &format!("did you mean `{}!`?", suggestion));
}
}
}
}).collect();
segments.push(ast::PathSegment {
identifier: last_identifier,
- parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+ parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
let mut path = trait_path;
path.segments.push(ast::PathSegment {
identifier: ident,
- parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+ parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
let extname = pth.segments[0].identifier.name;
match fld.cx.syntax_env.find(extname) {
None => {
- fld.cx.span_err(
+ let mut err = fld.cx.struct_span_err(
pth.span,
&format!("macro undefined: '{}!'",
&extname));
- fld.cx.suggest_macro_name(&extname.as_str(), pth.span);
+ fld.cx.suggest_macro_name(&extname.as_str(), pth.span, &mut err);
+ err.emit();
// let compilation continue
None
for attr in attrs {
let mut is_use = attr.check_name("macro_use");
if attr.check_name("macro_escape") {
- fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use");
+ let mut err =
+ fld.cx.struct_span_warn(attr.span,
+ "macro_escape is a deprecated synonym for macro_use");
is_use = true;
if let ast::AttrStyle::Inner = attr.node.style {
- fld.cx.fileline_help(attr.span, "consider an outer attribute, \
- #[macro_use] mod ...");
+ err.fileline_help(attr.span, "consider an outer attribute, \
+ #[macro_use] mod ...").emit();
+ } else {
+ err.emit();
}
};
let cx_expr = panictry!(p.parse_expr());
if !panictry!(p.eat(&token::Comma)) {
- panic!(p.fatal("expected token `,`"));
+ let _ = p.diagnostic().fatal("expected token `,`");
}
let tts = panictry!(p.parse_all_token_trees());
while self.p.token != token::Eof {
match panictry!(self.p.parse_item()) {
Some(item) => ret.push(item),
- None => panic!(self.p.span_fatal(
- self.p.span,
- &format!("expected item, found `{}`",
- self.p.this_token_to_string())
- ))
+ None => panic!(self.p.diagnostic().span_fatal(self.p.span,
+ &format!("expected item, found `{}`",
+ self.p.this_token_to_string())))
}
}
Some(ret)
use ast::{TokenTree, Name, Ident};
use codemap::{BytePos, mk_sp, Span, Spanned};
use codemap;
+use errors::FatalError;
use parse::lexer::*; //resolve bug?
use parse::ParseSess;
use parse::parser::{LifetimeAndTypesWithoutColons, Parser};
}
}
-pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
+pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
match name {
"tt" => {
p.quote_depth += 1; //but in theory, non-quoted tts might be useful
- let res = token::NtTT(P(panictry!(p.parse_token_tree())));
+ let res: ::parse::PResult<'a, _> = p.parse_token_tree();
+ let res = token::NtTT(P(panictry!(res)));
p.quote_depth -= 1;
return res;
}
match name {
"item" => match panictry!(p.parse_item()) {
Some(i) => token::NtItem(i),
- None => panic!(p.fatal("expected an item keyword"))
+ None => {
+ p.fatal("expected an item keyword").emit();
+ panic!(FatalError);
+ }
},
"block" => token::NtBlock(panictry!(p.parse_block())),
"stmt" => match panictry!(p.parse_stmt()) {
Some(s) => token::NtStmt(s),
- None => panic!(p.fatal("expected a statement"))
+ None => {
+ p.fatal("expected a statement").emit();
+ panic!(FatalError);
+ }
},
"pat" => token::NtPat(panictry!(p.parse_pat())),
"expr" => token::NtExpr(panictry!(p.parse_expr())),
}
_ => {
let token_str = pprust::token_to_string(&p.token);
- panic!(p.fatal(&format!("expected ident, found {}",
- &token_str[..])))
+ p.fatal(&format!("expected ident, found {}",
+ &token_str[..])).emit();
+ panic!(FatalError)
}
},
"path" => {
},
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
_ => {
- panic!(p.span_fatal_help(sp,
- &format!("invalid fragment specifier `{}`", name),
- "valid fragment specifiers are `ident`, `block`, \
- `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
- and `item`"))
+ p.span_fatal_help(sp,
+ &format!("invalid fragment specifier `{}`", name),
+ "valid fragment specifiers are `ident`, `block`, \
+ `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
+ and `item`").emit();
+ panic!(FatalError);
}
}
}
following",
token_str);
let span = parser.span;
- parser.span_err(span, &msg[..]);
-
+ let mut err = parser.diagnostic().struct_span_err(span, &msg[..]);
let msg = format!("caused by the macro expansion here; the usage \
of `{}!` is likely invalid in {} context",
self.macro_ident, context);
- parser.span_note(self.site_span, &msg[..]);
+ err.span_note(self.site_span, &msg[..])
+ .emit();
}
}
}
Some(stmt) => ret.push(stmt),
None => (),
},
- Err(_) => break,
+ Err(mut e) => {
+ e.emit();
+ break;
+ }
}
}
}
GateIssue::Library(lib) => lib,
};
- if let Some(n) = issue {
- diag.span_err(span, &format!("{} (see issue #{})", explain, n));
+ let mut err = if let Some(n) = issue {
+ diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
} else {
- diag.span_err(span, explain);
- }
+ diag.struct_span_err(span, explain)
+ };
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
- if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
- diag.fileline_help(span, &format!("add #![feature({})] to the \
- crate attributes to enable",
- feature));
+ if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() {
+ err.emit();
+ return;
+ }
+ err.fileline_help(span, &format!("add #![feature({})] to the \
+ crate attributes to enable",
+ feature));
+ err.emit();
}
pub const EXPLAIN_ASM: &'static str =
self.gate_feature("braced_empty_structs", span,
"empty structs and enum variants with braces are unstable");
} else if s.is_tuple() {
- self.context.span_handler.span_err(span, "empty tuple structs and enum variants \
- are not allowed, use unit structs and \
- enum variants instead");
- self.context.span_handler.span_help(span, "remove trailing `()` to make a unit \
- struct or unit enum variant");
+ self.context.span_handler.struct_span_err(span, "empty tuple structs and enum \
+ variants are not allowed, use \
+ unit structs and enum variants \
+ instead")
+ .span_help(span, "remove trailing `()` to make a unit \
+ struct or unit enum variant")
+ .emit();
}
}
visit::walk_struct_def(self, s)
-> PathParameters
{
match path_parameters {
- AngleBracketedParameters(data) =>
- AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
- ParenthesizedParameters(data) =>
- ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)),
+ PathParameters::AngleBracketed(data) =>
+ PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)),
+ PathParameters::Parenthesized(data) =>
+ PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)),
}
}
extern crate serialize as rustc_serialize; // used by deriving
-// A variant of 'try!' that panics on Err(FatalError). This is used as a
-// crutch on the way towards a non-panic!-prone parser. It should be used
-// for fatal parsing errors; eventually we plan to convert all code using
-// panictry to just use normal try
+// A variant of 'try!' that panics on an Err. This is used as a crutch on the
+// way towards a non-panic!-prone parser. It should be used for fatal parsing
+// errors; eventually we plan to convert all code using panictry to just use
+// normal try.
+// Exported for syntax_ext, not meant for general use.
+#[macro_export]
macro_rules! panictry {
($e:expr) => ({
use std::result::Result::{Ok, Err};
- use errors::FatalError;
+ use $crate::errors::FatalError;
match $e {
Ok(e) => e,
- Err(FatalError) => panic!(FatalError)
+ Err(mut e) => {
+ e.emit();
+ panic!(FatalError);
+ }
}
})
}
impl<'a> Parser<'a> {
/// Parse attributes that appear before an item
- pub fn parse_outer_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
+ pub fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = Vec::new();
loop {
debug!("parse_outer_attributes: self.token={:?}",
///
/// If permit_inner is true, then a leading `!` indicates an inner
/// attribute
- pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<ast::Attribute> {
+ pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
debug!("parse_attributes: permit_inner={:?} self.token={:?}",
permit_inner, self.token);
let (span, value, mut style) = match self.token {
try!(self.bump());
if !permit_inner {
let span = self.span;
- self.span_err(span,
- "an inner attribute is not permitted in \
- this context");
- self.fileline_help(span,
- "place inner attribute at the top of the module or block");
+ self.diagnostic().struct_span_err(span,
+ "an inner attribute is not permitted in \
+ this context")
+ .fileline_help(span,
+ "place inner attribute at the top of \
+ the module or block")
+ .emit()
}
ast::AttrStyle::Inner
} else {
/// terminated by a semicolon.
/// matches inner_attrs*
- pub fn parse_inner_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
+ pub fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = vec![];
loop {
match self.token {
/// matches meta_item = IDENT
/// | IDENT = lit
/// | IDENT meta_seq
- pub fn parse_meta_item(&mut self) -> PResult<P<ast::MetaItem>> {
+ pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
let nt_meta = match self.token {
token::Interpolated(token::NtMeta(ref e)) => {
Some(e.clone())
}
/// matches meta_seq = ( COMMASEP(meta_item) )
- fn parse_meta_seq(&mut self) -> PResult<Vec<P<ast::MetaItem>>> {
+ fn parse_meta_seq(&mut self) -> PResult<'a, Vec<P<ast::MetaItem>>> {
self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
- |p| p.parse_meta_item())
+ |p: &mut Parser<'a>| p.parse_meta_item())
}
}
use ast;
use codemap::{BytePos, CharPos, CodeMap, Pos, Span};
use codemap;
-use errors::{FatalError, Handler};
+use errors::{FatalError, Handler, DiagnosticBuilder};
use ext::tt::transcribe::tt_next_token;
use parse::token::str_to_ident;
use parse::token;
self.span_diagnostic.span_err(sp, m)
}
- /// Suggest some help with a given span.
- pub fn help_span(&self, sp: Span, m: &str) {
- self.span_diagnostic.span_help(sp, m)
- }
/// Report a fatal error spanning [`from_pos`, `to_pos`).
fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
self.err_span(codemap::mk_sp(from_pos, to_pos), m)
}
- /// Suggest some help spanning [`from_pos`, `to_pos`).
- fn help_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) {
- self.help_span(codemap::mk_sp(from_pos, to_pos), m)
- }
-
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
/// escaped character to the error message
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
for c in c.escape_default() { m.push(c) }
self.fatal_span_(from_pos, to_pos, &m[..])
}
+ fn struct_fatal_span_char(&self,
+ from_pos: BytePos,
+ to_pos: BytePos,
+ m: &str,
+ c: char)
+ -> DiagnosticBuilder<'a> {
+ let mut m = m.to_string();
+ m.push_str(": ");
+ for c in c.escape_default() { m.push(c) }
+ self.span_diagnostic.struct_span_fatal(codemap::mk_sp(from_pos, to_pos), &m[..])
+ }
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
/// escaped character to the error message
for c in c.escape_default() { m.push(c) }
self.err_span_(from_pos, to_pos, &m[..]);
}
+ fn struct_err_span_char(&self,
+ from_pos: BytePos,
+ to_pos: BytePos,
+ m: &str,
+ c: char)
+ -> DiagnosticBuilder<'a> {
+ let mut m = m.to_string();
+ m.push_str(": ");
+ for c in c.escape_default() { m.push(c) }
+ self.span_diagnostic.struct_span_err(codemap::mk_sp(from_pos, to_pos), &m[..])
+ }
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending the
/// offending string to the error message
let valid = if self.curr_is('{') {
self.scan_unicode_escape(delim) && !ascii_only
} else {
- self.err_span_(start, self.last_pos,
- "incorrect unicode escape sequence");
- self.help_span_(start, self.last_pos,
- "format of unicode escape sequences is `\\u{…}`");
+ let span = codemap::mk_sp(start, self.last_pos);
+ self.span_diagnostic.struct_span_err(span,
+ "incorrect unicode escape sequence")
+ .span_help(span,
+ "format of unicode escape sequences is `\\u{…}`")
+ .emit();
false
};
if ascii_only {
}
c => {
let last_pos = self.last_pos;
- self.err_span_char(
+ let mut err = self.struct_err_span_char(
escaped_pos, last_pos,
if ascii_only { "unknown byte escape" }
else { "unknown character escape" },
c);
if e == '\r' {
- self.help_span_(escaped_pos, last_pos,
+ err.span_help(codemap::mk_sp(escaped_pos, last_pos),
"this is an isolated carriage return; consider checking \
- your editor and version control settings")
+ your editor and version control settings");
}
if (e == '{' || e == '}') && !ascii_only {
- self.help_span_(escaped_pos, last_pos,
+ err.span_help(codemap::mk_sp(escaped_pos, last_pos),
"if used in a formatting string, \
- curly braces are escaped with `{{` and `}}`")
+ curly braces are escaped with `{{` and `}}`");
}
+ err.emit();
false
}
}
c => {
let last_bpos = self.last_pos;
let bpos = self.pos;
- unicode_chars::check_for_substitution(&self, c);
- panic!(self.fatal_span_char(last_bpos, bpos, "unknown start of token", c))
+ let mut err = self.struct_fatal_span_char(last_bpos,
+ bpos,
+ "unknown start of token",
+ c);
+ unicode_chars::check_for_substitution(&self, c, &mut err);
+ err.emit();
+ panic!(FatalError);
}
}
}
// http://www.unicode.org/Public/security/revision-06/confusables.txt
use codemap::mk_sp as make_span;
+use errors::DiagnosticBuilder;
use super::StringReader;
const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
('=', "Equals Sign"),
('>', "Greater-Than Sign"), ];
-pub fn check_for_substitution(reader: &StringReader, ch: char) {
+pub fn check_for_substitution<'a>(reader: &StringReader<'a>,
+ ch: char,
+ err: &mut DiagnosticBuilder<'a>) {
UNICODE_ARRAY
.iter()
.find(|&&(c, _, _)| c == ch)
let msg =
format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
ch, u_name, ascii_char, ascii_name);
- reader.help_span(span, &msg);
+ err.span_help(span, &msg);
},
None => {
reader
use ast;
use codemap::{self, Span, CodeMap, FileMap};
-use errors::{Handler, ColorConfig, FatalError};
+use errors::{Handler, ColorConfig, DiagnosticBuilder};
use parse::parser::Parser;
use parse::token::InternedString;
use ptr::P;
use std::rc::Rc;
use std::str;
-pub type PResult<T> = Result<T, FatalError>;
+pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
#[macro_use]
pub mod parser;
cfg: ast::CrateConfig,
sess: &ParseSess
) -> ast::Crate {
- panictry!(new_parser_from_file(sess, cfg, input).parse_crate_mod())
- // why is there no p.abort_if_errors here?
+ let mut parser = new_parser_from_file(sess, cfg, input);
+ abort_if_errors(parser.parse_crate_mod(), &parser)
}
pub fn parse_crate_attrs_from_file(
cfg: ast::CrateConfig,
sess: &ParseSess
) -> Vec<ast::Attribute> {
- // FIXME: maybe_aborted?
- panictry!(new_parser_from_file(sess, cfg, input).parse_inner_attributes())
+ let mut parser = new_parser_from_file(sess, cfg, input);
+ abort_if_errors(parser.parse_inner_attributes(), &parser)
}
pub fn parse_crate_from_source_str(name: String,
result
}
+fn abort_if_errors<'a, T>(result: PResult<'a, T>, p: &Parser) -> T {
+ match result {
+ Ok(c) => {
+ p.abort_if_errors();
+ c
+ }
+ Err(mut e) => {
+ e.emit();
+ p.abort_if_errors();
+ unreachable!();
+ }
+ }
+}
+
/// Parse a string representing a character literal into its final form.
/// Rather than just accepting/rejecting a given literal, unescapes it as
/// well. Can take any slice prefixed by a character escape. Returns the
Some(suf) => {
if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) {
// if it looks like a width, lets try to be helpful.
- sd.span_err(sp, &format!("invalid width `{}` for float literal", &suf[1..]));
- sd.fileline_help(sp, "valid widths are 32 and 64");
+ sd.struct_span_err(sp, &format!("invalid width `{}` for float literal", &suf[1..]))
+ .fileline_help(sp, "valid widths are 32 and 64")
+ .emit();
} else {
- sd.span_err(sp, &format!("invalid suffix `{}` for float literal", suf));
- sd.fileline_help(sp, "valid suffixes are `f32` and `f64`");
+ sd.struct_span_err(sp, &format!("invalid suffix `{}` for float literal", suf))
+ .fileline_help(sp, "valid suffixes are `f32` and `f64`")
+ .emit();
}
ast::LitFloatUnsuffixed(data)
// i<digits> and u<digits> look like widths, so lets
// give an error message along those lines
if looks_like_width_suffix(&['i', 'u'], suf) {
- sd.span_err(sp, &format!("invalid width `{}` for integer literal",
- &suf[1..]));
- sd.fileline_help(sp, "valid widths are 8, 16, 32 and 64");
+ sd.struct_span_err(sp, &format!("invalid width `{}` for integer literal",
+ &suf[1..]))
+ .fileline_help(sp, "valid widths are 8, 16, 32 and 64")
+ .emit();
} else {
- sd.span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf));
- sd.fileline_help(sp, "the suffix must be one of the integral types \
- (`u32`, `isize`, etc)");
+ sd.struct_span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf))
+ .fileline_help(sp, "the suffix must be one of the integral types \
+ (`u32`, `isize`, etc)")
+ .emit();
}
ty
kind_str: &str,
desc: &str,
error: bool) {
- if error {
- self.span_err(sp, &format!("obsolete syntax: {}", kind_str));
+ let mut err = if error {
+ self.diagnostic().struct_span_err(sp, &format!("obsolete syntax: {}", kind_str))
} else {
- self.span_warn(sp, &format!("obsolete syntax: {}", kind_str));
- }
+ self.diagnostic().struct_span_warn(sp, &format!("obsolete syntax: {}", kind_str))
+ };
if !self.obsolete_set.contains(&kind) &&
(error || self.sess.span_diagnostic.can_emit_warnings) {
- self.sess
- .span_diagnostic
- .note(&format!("{}", desc));
+ err.note(&format!("{}", desc));
self.obsolete_set.insert(kind);
}
+ err.emit();
}
}
use ast;
use ast_util::{self, ident_to_path};
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
-use errors::{self, FatalError};
+use errors::{self, DiagnosticBuilder};
use ext::tt::macro_parser;
use parse;
use parse::classify;
use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed};
use parse::lexer::{Reader, TokenAndSpan};
use parse::obsolete::{ParserObsoleteMethods, ObsoleteSyntax};
-use parse::token::{self, MatchNt, SubstNt, SpecialVarNt, InternedString};
+use parse::token::{self, intern, MatchNt, SubstNt, SpecialVarNt, InternedString};
use parse::token::{keywords, special_idents, SpecialMacroVar};
use parse::{new_sub_parser_from_file, ParseSess};
use util::parser::{AssocOp, Fixity};
Parser::token_to_string(&self.token)
}
- pub fn unexpected_last(&self, t: &token::Token) -> FatalError {
+ pub fn unexpected_last(&self, t: &token::Token) -> DiagnosticBuilder<'a> {
let token_str = Parser::token_to_string(t);
let last_span = self.last_span;
self.span_fatal(last_span, &format!("unexpected token: `{}`",
token_str))
}
- pub fn unexpected(&mut self) -> FatalError {
+ pub fn unexpected(&mut self) -> DiagnosticBuilder<'a> {
match self.expect_one_of(&[], &[]) {
Err(e) => e,
Ok(_) => unreachable!()
/// Expect and consume the token t. Signal an error if
/// the next token is not t.
- pub fn expect(&mut self, t: &token::Token) -> PResult<()> {
+ pub fn expect(&mut self, t: &token::Token) -> PResult<'a, ()> {
if self.expected_tokens.is_empty() {
if self.token == *t {
self.bump()
/// anything. Signal a fatal error if next token is unexpected.
pub fn expect_one_of(&mut self,
edible: &[token::Token],
- inedible: &[token::Token]) -> PResult<()>{
+ inedible: &[token::Token]) -> PResult<'a, ()>{
fn tokens_to_string(tokens: &[TokenType]) -> String {
let mut i = tokens.iter();
// This might be a sign we need a connect method on Iterator.
/// true if and only if input was consumed for recovery.
pub fn check_for_erroneous_unit_struct_expecting(&mut self,
expected: &[token::Token])
- -> PResult<bool> {
+ -> PResult<'a, bool> {
if self.token == token::OpenDelim(token::Brace)
&& expected.iter().all(|t| *t != token::OpenDelim(token::Brace))
&& self.look_ahead(1, |t| *t == token::CloseDelim(token::Brace)) {
/// followed by some token from the set edible + inedible. Recover
/// from anticipated input errors, discarding erroneous characters.
pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token],
- inedible: &[token::Token]) -> PResult<()> {
+ inedible: &[token::Token]) -> PResult<'a, ()> {
debug!("commit_expr {:?}", e);
if let ExprPath(..) = e.node {
// might be unit-struct construction; check for recoverableinput error.
self.expect_one_of(edible, inedible)
}
- pub fn commit_expr_expecting(&mut self, e: &Expr, edible: token::Token) -> PResult<()> {
+ pub fn commit_expr_expecting(&mut self, e: &Expr, edible: token::Token) -> PResult<'a, ()> {
self.commit_expr(e, &[edible], &[])
}
/// followed by some token from the set edible + inedible. Check
/// for recoverable input errors, discarding erroneous characters.
pub fn commit_stmt(&mut self, edible: &[token::Token],
- inedible: &[token::Token]) -> PResult<()> {
+ inedible: &[token::Token]) -> PResult<'a, ()> {
if self.last_token
.as_ref()
.map_or(false, |t| t.is_ident() || t.is_path()) {
self.expect_one_of(edible, inedible)
}
- pub fn commit_stmt_expecting(&mut self, edible: token::Token) -> PResult<()> {
+ pub fn commit_stmt_expecting(&mut self, edible: token::Token) -> PResult<'a, ()> {
self.commit_stmt(&[edible], &[])
}
- pub fn parse_ident(&mut self) -> PResult<ast::Ident> {
+ pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
self.check_strict_keywords();
try!(self.check_reserved_keywords());
match self.token {
}
}
- pub fn parse_ident_or_self_type(&mut self) -> PResult<ast::Ident> {
+ pub fn parse_ident_or_self_type(&mut self) -> PResult<'a, ast::Ident> {
if self.is_self_type_ident() {
self.expect_self_type_ident()
} else {
}
}
- pub fn parse_path_list_item(&mut self) -> PResult<ast::PathListItem> {
+ pub fn parse_path_list_item(&mut self) -> PResult<'a, ast::PathListItem> {
let lo = self.span.lo;
let node = if try!(self.eat_keyword(keywords::SelfValue)) {
let rename = try!(self.parse_rename());
/// Consume token 'tok' if it exists. Returns true if the given
/// token was present, false otherwise.
- pub fn eat(&mut self, tok: &token::Token) -> PResult<bool> {
+ pub fn eat(&mut self, tok: &token::Token) -> PResult<'a, bool> {
let is_present = self.check(tok);
if is_present { try!(self.bump())}
Ok(is_present)
/// If the next token is the given keyword, eat it and return
/// true. Otherwise, return false.
- pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> PResult<bool> {
+ pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, bool> {
if self.check_keyword(kw) {
try!(self.bump());
Ok(true)
}
}
- pub fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> PResult<bool> {
+ pub fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> PResult<'a, bool> {
if self.token.is_keyword(kw) {
try!(self.bump());
Ok(true)
/// If the given word is not a keyword, signal an error.
/// If the next token is not the given word, signal an error.
/// Otherwise, eat it.
- pub fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<()> {
+ pub fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> {
if !try!(self.eat_keyword(kw) ){
self.expect_one_of(&[], &[])
} else {
}
/// Signal an error if the current token is a reserved keyword
- pub fn check_reserved_keywords(&mut self) -> PResult<()>{
+ pub fn check_reserved_keywords(&mut self) -> PResult<'a, ()>{
if self.token.is_reserved_keyword() {
let token_str = self.this_token_to_string();
- Err(self.fatal(&format!("`{}` is a reserved keyword",
- token_str)))
+ Err(self.fatal(&format!("`{}` is a reserved keyword", token_str)))
} else {
Ok(())
}
/// Expect and consume an `&`. If `&&` is seen, replace it with a single
/// `&` and continue. If an `&` is not seen, signal an error.
- fn expect_and(&mut self) -> PResult<()> {
+ fn expect_and(&mut self) -> PResult<'a, ()> {
self.expected_tokens.push(TokenType::Token(token::BinOp(token::And)));
match self.token {
token::BinOp(token::And) => self.bump(),
///
/// This is meant to be used when parsing generics on a path to get the
/// starting token.
- fn eat_lt(&mut self) -> PResult<bool> {
+ fn eat_lt(&mut self) -> PResult<'a, bool> {
self.expected_tokens.push(TokenType::Token(token::Lt));
match self.token {
token::Lt => { try!(self.bump()); Ok(true)}
}
}
- fn expect_lt(&mut self) -> PResult<()> {
+ fn expect_lt(&mut self) -> PResult<'a, ()> {
if !try!(self.eat_lt()) {
self.expect_one_of(&[], &[])
} else {
/// Expect and consume a GT. if a >> is seen, replace it
/// with a single > and continue. If a GT is not seen,
/// signal an error.
- pub fn expect_gt(&mut self) -> PResult<()> {
+ pub fn expect_gt(&mut self) -> PResult<'a, ()> {
self.expected_tokens.push(TokenType::Token(token::Gt));
match self.token {
token::Gt => self.bump(),
pub fn parse_seq_to_before_gt_or_return<T, F>(&mut self,
sep: Option<token::Token>,
mut f: F)
- -> PResult<(P<[T]>, bool)> where
- F: FnMut(&mut Parser) -> PResult<Option<T>>,
+ -> PResult<'a, (P<[T]>, bool)>
+ where F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>,
{
let mut v = Vec::new();
// This loop works by alternating back and forth between parsing types
pub fn parse_seq_to_before_gt<T, F>(&mut self,
sep: Option<token::Token>,
mut f: F)
- -> PResult<P<[T]>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, P<[T]>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let (result, returned) = try!(self.parse_seq_to_before_gt_or_return(sep,
|p| Ok(Some(try!(f(p))))));
pub fn parse_seq_to_gt<T, F>(&mut self,
sep: Option<token::Token>,
f: F)
- -> PResult<P<[T]>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, P<[T]>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let v = try!(self.parse_seq_to_before_gt(sep, f));
try!(self.expect_gt());
pub fn parse_seq_to_gt_or_return<T, F>(&mut self,
sep: Option<token::Token>,
f: F)
- -> PResult<(P<[T]>, bool)> where
- F: FnMut(&mut Parser) -> PResult<Option<T>>,
+ -> PResult<'a, (P<[T]>, bool)> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>,
{
let (v, returned) = try!(self.parse_seq_to_before_gt_or_return(sep, f));
if !returned {
ket: &token::Token,
sep: SeqSep,
f: F)
- -> PResult<Vec<T>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, Vec<T>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let val = try!(self.parse_seq_to_before_end(ket, sep, f));
try!(self.bump());
ket: &token::Token,
sep: SeqSep,
mut f: F)
- -> PResult<Vec<T>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, Vec<T>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let mut first: bool = true;
let mut v = vec!();
ket: &token::Token,
sep: SeqSep,
f: F)
- -> PResult<Vec<T>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, Vec<T>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
try!(self.expect(bra));
let result = try!(self.parse_seq_to_before_end(ket, sep, f));
ket: &token::Token,
sep: SeqSep,
f: F)
- -> PResult<Vec<T>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, Vec<T>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let result = try!(self.parse_unspanned_seq(bra, ket, sep, f));
if result.is_empty() {
ket: &token::Token,
sep: SeqSep,
f: F)
- -> PResult<Spanned<Vec<T>>> where
- F: FnMut(&mut Parser) -> PResult<T>,
+ -> PResult<'a, Spanned<Vec<T>>> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let lo = self.span.lo;
try!(self.expect(bra));
}
/// Advance the parser by one token
- pub fn bump(&mut self) -> PResult<()> {
+ pub fn bump(&mut self) -> PResult<'a, ()> {
self.last_span = self.span;
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
self.last_token = if self.token.is_ident() ||
}
/// Advance the parser by one token and return the bumped token.
- pub fn bump_and_get(&mut self) -> PResult<token::Token> {
+ pub fn bump_and_get(&mut self) -> PResult<'a, token::Token> {
let old_token = mem::replace(&mut self.token, token::Underscore);
try!(self.bump());
Ok(old_token)
}
f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok)
}
- pub fn fatal(&self, m: &str) -> errors::FatalError {
- self.sess.span_diagnostic.span_fatal(self.span, m)
+ pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
+ self.sess.span_diagnostic.struct_span_fatal(self.span, m)
}
- pub fn span_fatal(&self, sp: Span, m: &str) -> errors::FatalError {
- self.sess.span_diagnostic.span_fatal(sp, m)
+ pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> {
+ self.sess.span_diagnostic.struct_span_fatal(sp, m)
}
- pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> errors::FatalError {
- self.span_err(sp, m);
- self.fileline_help(sp, help);
- errors::FatalError
- }
- pub fn span_note(&self, sp: Span, m: &str) {
- self.sess.span_diagnostic.span_note(sp, m)
- }
- pub fn span_help(&self, sp: Span, m: &str) {
- self.sess.span_diagnostic.span_help(sp, m)
- }
- pub fn span_suggestion(&self, sp: Span, m: &str, n: String) {
- self.sess.span_diagnostic.span_suggestion(sp, m, n)
- }
- pub fn fileline_help(&self, sp: Span, m: &str) {
- self.sess.span_diagnostic.fileline_help(sp, m)
+ pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> {
+ let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m);
+ err.fileline_help(sp, help);
+ err
}
pub fn bug(&self, m: &str) -> ! {
self.sess.span_diagnostic.span_bug(self.span, m)
self.sess.span_diagnostic.abort_if_errors();
}
+ pub fn diagnostic(&self) -> &'a errors::Handler {
+ &self.sess.span_diagnostic
+ }
+
pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString {
id.name.as_str()
}
}
}
- pub fn parse_for_in_type(&mut self) -> PResult<Ty_> {
+ pub fn parse_for_in_type(&mut self) -> PResult<'a, Ty_> {
/*
Parses whatever can come after a `for` keyword in a type.
The `for` has already been consumed.
}
}
- pub fn parse_ty_path(&mut self) -> PResult<Ty_> {
+ pub fn parse_ty_path(&mut self) -> PResult<'a, Ty_> {
Ok(TyPath(None, try!(self.parse_path(LifetimeAndTypesWithoutColons))))
}
/// parse a TyBareFn type:
- pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> PResult<Ty_> {
+ pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> PResult<'a, Ty_> {
/*
[unsafe] [extern "ABI"] fn <'lt> (S) -> T
}
/// Parses an obsolete closure kind (`&:`, `&mut:`, or `:`).
- pub fn parse_obsolete_closure_kind(&mut self) -> PResult<()> {
+ pub fn parse_obsolete_closure_kind(&mut self) -> PResult<'a, ()> {
let lo = self.span.lo;
if
self.check(&token::BinOp(token::And)) &&
Ok(())
}
- pub fn parse_unsafety(&mut self) -> PResult<Unsafety> {
+ pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
if try!(self.eat_keyword(keywords::Unsafe)) {
return Ok(Unsafety::Unsafe);
} else {
}
/// Parse the items in a trait declaration
- pub fn parse_trait_items(&mut self) -> PResult<Vec<P<TraitItem>>> {
+ pub fn parse_trait_items(&mut self) -> PResult<'a, Vec<P<TraitItem>>> {
self.parse_unspanned_seq(
&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
seq_sep_none(),
- |p| -> PResult<P<TraitItem>> {
+ |p| -> PResult<'a, P<TraitItem>> {
maybe_whole!(no_clone p, NtTraitItem);
let mut attrs = try!(p.parse_outer_attributes());
let lo = p.span.lo;
let ident = try!(p.parse_ident());
let mut generics = try!(p.parse_generics());
- let (explicit_self, d) = try!(p.parse_fn_decl_with_self(|p|{
+ let (explicit_self, d) = try!(p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
// This is somewhat dubious; We don't want to allow
// argument names to be left off if there is a
// definition...
}
/// Parse a possibly mutable type
- pub fn parse_mt(&mut self) -> PResult<MutTy> {
+ pub fn parse_mt(&mut self) -> PResult<'a, MutTy> {
let mutbl = try!(self.parse_mutability());
let t = try!(self.parse_ty());
Ok(MutTy { ty: t, mutbl: mutbl })
}
/// Parse optional return type [ -> TY ] in function decl
- pub fn parse_ret_ty(&mut self) -> PResult<FunctionRetTy> {
+ pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
if try!(self.eat(&token::RArrow) ){
if try!(self.eat(&token::Not) ){
Ok(NoReturn(self.last_span))
}
/// Parse a type in a context where `T1+T2` is allowed.
- pub fn parse_ty_sum(&mut self) -> PResult<P<Ty>> {
+ pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> {
let lo = self.span.lo;
let lhs = try!(self.parse_ty());
}
/// Parse a type.
- pub fn parse_ty(&mut self) -> PResult<P<Ty>> {
+ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
maybe_whole!(no_clone self, NtTy);
let lo = self.span.lo;
Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp}))
}
- pub fn parse_borrowed_pointee(&mut self) -> PResult<Ty_> {
+ pub fn parse_borrowed_pointee(&mut self) -> PResult<'a, Ty_> {
// look for `&'lt` or `&'foo ` and interpret `foo` as the region name:
let opt_lifetime = try!(self.parse_opt_lifetime());
return Ok(TyRptr(opt_lifetime, mt));
}
- pub fn parse_ptr(&mut self) -> PResult<MutTy> {
+ pub fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
let mutbl = if try!(self.eat_keyword(keywords::Mut) ){
MutMutable
} else if try!(self.eat_keyword(keywords::Const) ){
/// This version of parse arg doesn't necessarily require
/// identifier names.
- pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<Arg> {
+ pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
maybe_whole!(no_clone self, NtArg);
let pat = if require_name || self.is_named_argument() {
}
/// Parse a single function argument
- pub fn parse_arg(&mut self) -> PResult<Arg> {
+ pub fn parse_arg(&mut self) -> PResult<'a, Arg> {
self.parse_arg_general(true)
}
/// Parse an argument in a lambda header e.g. |arg, arg|
- pub fn parse_fn_block_arg(&mut self) -> PResult<Arg> {
+ pub fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
let pat = try!(self.parse_pat());
let t = if try!(self.eat(&token::Colon) ){
try!(self.parse_ty_sum())
})
}
- pub fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<Option<P<ast::Expr>>> {
+ pub fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
if self.check(&token::Semi) {
try!(self.bump());
Ok(Some(try!(self.parse_expr())))
}
/// Matches token_lit = LIT_INTEGER | ...
- pub fn lit_from_token(&self, tok: &token::Token) -> PResult<Lit_> {
+ pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, Lit_> {
match *tok {
token::Interpolated(token::NtExpr(ref v)) => {
match v.node {
}
/// Matches lit = true | false | token_lit
- pub fn parse_lit(&mut self) -> PResult<Lit> {
+ pub fn parse_lit(&mut self) -> PResult<'a, Lit> {
let lo = self.span.lo;
let lit = if try!(self.eat_keyword(keywords::True) ){
LitBool(true)
}
/// matches '-' lit | lit
- pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<P<Expr>> {
+ pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
let minus_lo = self.span.lo;
let minus_present = try!(self.eat(&token::BinOp(token::Minus)));
let lo = self.span.lo;
/// `<T as U>::a`
/// `<T as U>::F::a::<S>`
pub fn parse_qualified_path(&mut self, mode: PathParsingMode)
- -> PResult<(QSelf, ast::Path)> {
+ -> PResult<'a, (QSelf, ast::Path)> {
let span = self.last_span;
let self_type = try!(self.parse_ty_sum());
let mut path = if try!(self.eat_keyword(keywords::As)) {
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
/// bounds are permitted and whether `::` must precede type parameter
/// groups.
- pub fn parse_path(&mut self, mode: PathParsingMode) -> PResult<ast::Path> {
+ pub fn parse_path(&mut self, mode: PathParsingMode) -> PResult<'a, ast::Path> {
// Check for a whole path...
let found = match self.token {
token::Interpolated(token::NtPath(_)) => Some(try!(self.bump_and_get())),
/// - `a::b<T,U>::c<V,W>`
/// - `a::b<T,U>::c(V) -> W`
/// - `a::b<T,U>::c(V)`
- pub fn parse_path_segments_without_colons(&mut self) -> PResult<Vec<ast::PathSegment>> {
+ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
let parameters = if try!(self.eat_lt() ){
let (lifetimes, types, bindings) = try!(self.parse_generic_values_after_lt());
- ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+ ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
let hi = self.last_span.hi;
- ast::ParenthesizedParameters(ast::ParenthesizedParameterData {
+ ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
span: mk_sp(lo, hi),
inputs: inputs,
output: output_ty,
/// Examples:
/// - `a::b::<T,U>::c`
- pub fn parse_path_segments_with_colons(&mut self) -> PResult<Vec<ast::PathSegment>> {
+ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
if try!(self.eat_lt() ){
// Consumed `a::b::<`, go look for types
let (lifetimes, types, bindings) = try!(self.parse_generic_values_after_lt());
+ let parameters = ast::AngleBracketedParameterData {
+ lifetimes: lifetimes,
+ types: P::from_vec(types),
+ bindings: P::from_vec(bindings),
+ };
segments.push(ast::PathSegment {
identifier: identifier,
- parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
- lifetimes: lifetimes,
- types: P::from_vec(types),
- bindings: P::from_vec(bindings),
- }),
+ parameters: ast::PathParameters::AngleBracketed(parameters),
});
// Consumed `a::b::<T,U>`, check for `::` before proceeding
/// Examples:
/// - `a::b::c`
- pub fn parse_path_segments_without_types(&mut self) -> PResult<Vec<ast::PathSegment>> {
+ pub fn parse_path_segments_without_types(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
}
/// parses 0 or 1 lifetime
- pub fn parse_opt_lifetime(&mut self) -> PResult<Option<ast::Lifetime>> {
+ pub fn parse_opt_lifetime(&mut self) -> PResult<'a, Option<ast::Lifetime>> {
match self.token {
token::Lifetime(..) => {
Ok(Some(try!(self.parse_lifetime())))
/// Parses a single lifetime
/// Matches lifetime = LIFETIME
- pub fn parse_lifetime(&mut self) -> PResult<ast::Lifetime> {
+ pub fn parse_lifetime(&mut self) -> PResult<'a, ast::Lifetime> {
match self.token {
token::Lifetime(i) => {
let span = self.span;
/// Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` where `lifetime_def =
/// lifetime [':' lifetimes]`
- pub fn parse_lifetime_defs(&mut self) -> PResult<Vec<ast::LifetimeDef>> {
+ pub fn parse_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> {
let mut res = Vec::new();
loop {
/// Parses zero or more comma separated lifetimes. Expects each lifetime to be followed by
/// either a comma or `>`. Used when parsing type parameter lists, where we expect something
/// like `<'a, 'b, T>`.
- pub fn parse_lifetimes(&mut self, sep: token::Token) -> PResult<Vec<ast::Lifetime>> {
+ pub fn parse_lifetimes(&mut self, sep: token::Token) -> PResult<'a, Vec<ast::Lifetime>> {
let mut res = Vec::new();
loop {
}
/// Parse mutability declaration (mut/const/imm)
- pub fn parse_mutability(&mut self) -> PResult<Mutability> {
+ pub fn parse_mutability(&mut self) -> PResult<'a, Mutability> {
if try!(self.eat_keyword(keywords::Mut) ){
Ok(MutMutable)
} else {
}
/// Parse ident COLON expr
- pub fn parse_field(&mut self) -> PResult<Field> {
+ pub fn parse_field(&mut self) -> PResult<'a, Field> {
let lo = self.span.lo;
let i = try!(self.parse_ident());
let hi = self.last_span.hi;
})
}
- fn expect_open_delim(&mut self) -> PResult<token::DelimToken> {
+ fn expect_open_delim(&mut self) -> PResult<'a, token::DelimToken> {
self.expected_tokens.push(TokenType::Token(token::Gt));
match self.token {
token::OpenDelim(delim) => {
/// NB: This does not parse outer attributes,
/// and is private because it only works
/// correctly if called from parse_dot_or_call_expr().
- fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
+ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
maybe_whole_expr!(self);
// Outer attributes are already parsed and will be
fn parse_or_use_outer_attributes(&mut self,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<ThinAttributes> {
+ -> PResult<'a, ThinAttributes> {
if let Some(attrs) = already_parsed_attrs {
Ok(attrs)
} else {
/// Parse a block or unsafe block
pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode,
attrs: ThinAttributes)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
let outer_attrs = attrs;
try!(self.expect(&token::OpenDelim(token::Brace)));
/// parse a.b or a(13) or a[4] or just a
pub fn parse_dot_or_call_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
let b = try!(self.parse_bottom_expr());
pub fn parse_dot_or_call_expr_with(&mut self,
e0: P<Expr>,
attrs: ThinAttributes)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
// Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code
// structure
)
}
- fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<P<Expr>> {
+ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
let mut e = e0;
let lo = e.span.lo;
let mut hi;
try!(self.bump());
let last_span = self.last_span;
let fstr = n.as_str();
- self.span_err(last_span,
- &format!("unexpected token: `{}`", n.as_str()));
+ let mut err = self.diagnostic().struct_span_err(last_span,
+ &format!("unexpected token: `{}`", n.as_str()));
if fstr.chars().all(|x| "0123456789.".contains(x)) {
let float = match fstr.parse::<f64>().ok() {
Some(f) => f,
None => continue,
};
- self.fileline_help(last_span,
+ err.fileline_help(last_span,
&format!("try parenthesizing the first index; e.g., `(foo.{}){}`",
float.trunc() as usize,
format!(".{}", fstr.splitn(2, ".").last().unwrap())));
}
+ err.emit();
self.abort_if_errors();
}
}
// Parse unquoted tokens after a `$` in a token tree
- fn parse_unquoted(&mut self) -> PResult<TokenTree> {
+ fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> {
let mut sp = self.span;
let (name, namep) = match self.token {
token::Dollar => {
}
}
- pub fn check_unknown_macro_variable(&mut self) -> PResult<()> {
+ pub fn check_unknown_macro_variable(&mut self) -> PResult<'a, ()> {
if self.quote_depth == 0 {
match self.token {
token::SubstNt(name, _) =>
/// Parse an optional separator followed by a Kleene-style
/// repetition token (+ or *).
- pub fn parse_sep_and_kleene_op(&mut self) -> PResult<(Option<token::Token>, ast::KleeneOp)> {
- fn parse_kleene_op(parser: &mut Parser) -> PResult<Option<ast::KleeneOp>> {
+ pub fn parse_sep_and_kleene_op(&mut self)
+ -> PResult<'a, (Option<token::Token>, ast::KleeneOp)> {
+ fn parse_kleene_op<'a>(parser: &mut Parser<'a>) -> PResult<'a, Option<ast::KleeneOp>> {
match parser.token {
token::BinOp(token::Star) => {
try!(parser.bump());
}
/// parse a single token tree from the input.
- pub fn parse_token_tree(&mut self) -> PResult<TokenTree> {
+ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
// FIXME #6994: currently, this is too eager. It
// parses token trees but also identifies TokenType::Sequence's
// and token::SubstNt's; it's too early to know yet
// not an EOF, and not the desired right-delimiter (if
// it were, parse_seq_to_before_end would have prevented
// reaching this point.
- fn parse_non_delim_tt_tok(p: &mut Parser) -> PResult<TokenTree> {
+ fn parse_non_delim_tt_tok<'b>(p: &mut Parser<'b>) -> PResult<'b, TokenTree> {
maybe_whole!(deref p, NtTT);
match p.token {
token::CloseDelim(_) => {
+ let token_str = p.this_token_to_string();
+ let mut err = p.fatal(
+ &format!("incorrect close delimiter: `{}`", token_str));
// This is a conservative error: only report the last unclosed delimiter. The
// previous unclosed delimiters could actually be closed! The parser just hasn't
// gotten to them yet.
- match p.open_braces.last() {
- None => {}
- Some(&sp) => p.span_note(sp, "unclosed delimiter"),
+ if let Some(&sp) = p.open_braces.last() {
+ err.span_note(sp, "unclosed delimiter");
};
- let token_str = p.this_token_to_string();
- Err(p.fatal(&format!("incorrect close delimiter: `{}`",
- token_str)))
+ Err(err)
},
/* we ought to allow different depths of unquotation */
token::Dollar | token::SubstNt(..) if p.quote_depth > 0 => {
match self.token {
token::Eof => {
let open_braces = self.open_braces.clone();
+ let mut err: DiagnosticBuilder<'a> =
+ self.fatal("this file contains an un-closed delimiter");
for sp in &open_braces {
- self.span_help(*sp, "did you mean to close this delimiter?");
+ err.span_help(*sp, "did you mean to close this delimiter?");
}
- // There shouldn't really be a span, but it's easier for the test runner
- // if we give it one
- return Err(self.fatal("this file contains an un-closed delimiter "));
+ return Err(err);
},
token::OpenDelim(delim) => {
// The span for beginning of the delimited section
// parse a stream of tokens into a list of TokenTree's,
// up to EOF.
- pub fn parse_all_token_trees(&mut self) -> PResult<Vec<TokenTree>> {
+ pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> {
let mut tts = Vec::new();
while self.token != token::Eof {
tts.push(try!(self.parse_token_tree()));
/// Parse a prefix-unary-operator expr
pub fn parse_prefix_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
let lo = self.span.lo;
let hi;
/// the expression.
pub fn parse_assoc_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
self.parse_assoc_expr_with(0, already_parsed_attrs.into())
}
pub fn parse_assoc_expr_with(&mut self,
min_prec: usize,
lhs: LhsExpr)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
expr
} else {
}
let rhs = try!(match op.fixity() {
- Fixity::Right => self.with_res(restrictions, |this|{
- this.parse_assoc_expr_with(op.precedence(), LhsExpr::NotYetParsed)
+ Fixity::Right => self.with_res(
+ restrictions - Restrictions::RESTRICTION_STMT_EXPR,
+ |this| {
+ this.parse_assoc_expr_with(op.precedence(),
+ LhsExpr::NotYetParsed)
}),
- Fixity::Left => self.with_res(restrictions, |this|{
- this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed)
+ Fixity::Left => self.with_res(
+ restrictions - Restrictions::RESTRICTION_STMT_EXPR,
+ |this| {
+ this.parse_assoc_expr_with(op.precedence() + 1,
+ LhsExpr::NotYetParsed)
}),
// We currently have no non-associative operators that are not handled above by
// the special cases. The code is here only for future convenience.
- Fixity::None => self.with_res(restrictions, |this|{
- this.parse_assoc_expr_with(op.precedence() + 1, LhsExpr::NotYetParsed)
+ Fixity::None => self.with_res(
+ restrictions - Restrictions::RESTRICTION_STMT_EXPR,
+ |this| {
+ this.parse_assoc_expr_with(op.precedence() + 1,
+ LhsExpr::NotYetParsed)
}),
});
ExprBinary(op, _, _) if op.node.is_comparison() => {
// respan to include both operators
let op_span = mk_sp(op.span.lo, self.span.hi);
- self.span_err(op_span,
+ let mut err = self.diagnostic().struct_span_err(op_span,
"chained comparison operators require parentheses");
if op.node == BiLt && *outer_op == AssocOp::Greater {
- self.fileline_help(op_span,
+ err.fileline_help(op_span,
"use `::<...>` instead of `<...>` if you meant to specify type arguments");
}
+ err.emit();
}
_ => {}
}
/// Parse prefix-forms of range notation: `..expr` and `..`
fn parse_prefix_range_expr(&mut self,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
debug_assert!(self.token == token::DotDot);
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
let lo = self.span.lo;
}
/// Parse an 'if' or 'if let' expression ('if' token already eaten)
- pub fn parse_if_expr(&mut self, attrs: ThinAttributes) -> PResult<P<Expr>> {
+ pub fn parse_if_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
if self.check_keyword(keywords::Let) {
return self.parse_if_let_expr(attrs);
}
/// Parse an 'if let' expression ('if' token already eaten)
pub fn parse_if_let_expr(&mut self, attrs: ThinAttributes)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
let lo = self.last_span.lo;
try!(self.expect_keyword(keywords::Let));
let pat = try!(self.parse_pat());
pub fn parse_lambda_expr(&mut self, lo: BytePos,
capture_clause: CaptureClause,
attrs: ThinAttributes)
- -> PResult<P<Expr>>
+ -> PResult<'a, P<Expr>>
{
let decl = try!(self.parse_fn_block_decl());
let body = match decl.output {
}
// `else` token already eaten
- pub fn parse_else_expr(&mut self) -> PResult<P<Expr>> {
+ pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
if try!(self.eat_keyword(keywords::If) ){
return self.parse_if_expr(None);
} else {
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
span_lo: BytePos,
- attrs: ThinAttributes) -> PResult<P<Expr>> {
+ attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
let pat = try!(self.parse_pat());
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
span_lo: BytePos,
- attrs: ThinAttributes) -> PResult<P<Expr>> {
+ attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
if self.token.is_keyword(keywords::Let) {
return self.parse_while_let_expr(opt_ident, span_lo, attrs);
}
/// Parse a 'while let' expression ('while' token already eaten)
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
span_lo: BytePos,
- attrs: ThinAttributes) -> PResult<P<Expr>> {
+ attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
try!(self.expect_keyword(keywords::Let));
let pat = try!(self.parse_pat());
try!(self.expect(&token::Eq));
// parse `loop {...}`, `loop` token already eaten
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
span_lo: BytePos,
- attrs: ThinAttributes) -> PResult<P<Expr>> {
+ attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
let attrs = attrs.append(iattrs.into_thin_attrs());
let hi = body.span.hi;
}
// `match` token already eaten
- fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<P<Expr>> {
+ fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
let match_span = self.last_span;
let lo = self.last_span.lo;
let discriminant = try!(self.parse_expr_res(
Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None));
- if let Err(e) = self.commit_expr_expecting(&*discriminant, token::OpenDelim(token::Brace)) {
+ if let Err(mut e) = self.commit_expr_expecting(&*discriminant,
+ token::OpenDelim(token::Brace)) {
if self.token == token::Token::Semi {
- self.span_note(match_span, "did you mean to remove this `match` keyword?");
+ e.span_note(match_span, "did you mean to remove this `match` keyword?");
}
return Err(e)
}
return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms), attrs));
}
- pub fn parse_arm(&mut self) -> PResult<Arm> {
+ pub fn parse_arm(&mut self) -> PResult<'a, Arm> {
maybe_whole!(no_clone self, NtArm);
let attrs = try!(self.parse_outer_attributes());
}
/// Parse an expression
- pub fn parse_expr(&mut self) -> PResult<P<Expr>> {
+ pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
self.parse_expr_res(Restrictions::empty(), None)
}
/// Evaluate the closure with restrictions in place.
///
/// After the closure is evaluated, restrictions are reset.
- pub fn with_res<F>(&mut self, r: Restrictions, f: F) -> PResult<P<Expr>>
- where F: FnOnce(&mut Self) -> PResult<P<Expr>> {
+ pub fn with_res<F>(&mut self, r: Restrictions, f: F) -> PResult<'a, P<Expr>>
+ where F: FnOnce(&mut Self) -> PResult<'a, P<Expr>>
+ {
let old = self.restrictions;
self.restrictions = r;
let r = f(self);
/// Parse an expression, subject to the given restrictions
pub fn parse_expr_res(&mut self, r: Restrictions,
already_parsed_attrs: Option<ThinAttributes>)
- -> PResult<P<Expr>> {
+ -> PResult<'a, P<Expr>> {
self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
}
/// Parse the RHS of a local variable declaration (e.g. '= 14;')
- fn parse_initializer(&mut self) -> PResult<Option<P<Expr>>> {
+ fn parse_initializer(&mut self) -> PResult<'a, Option<P<Expr>>> {
if self.check(&token::Eq) {
try!(self.bump());
Ok(Some(try!(self.parse_expr())))
}
/// Parse patterns, separated by '|' s
- fn parse_pats(&mut self) -> PResult<Vec<P<Pat>>> {
+ fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
let mut pats = Vec::new();
loop {
pats.push(try!(self.parse_pat()));
};
}
- fn parse_pat_tuple_elements(&mut self) -> PResult<Vec<P<Pat>>> {
+ fn parse_pat_tuple_elements(&mut self) -> PResult<'a, Vec<P<Pat>>> {
let mut fields = vec![];
if !self.check(&token::CloseDelim(token::Paren)) {
fields.push(try!(self.parse_pat()));
fn parse_pat_vec_elements(
&mut self,
- ) -> PResult<(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> {
+ ) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> {
let mut before = Vec::new();
let mut slice = None;
let mut after = Vec::new();
}
/// Parse the fields of a struct-like pattern
- fn parse_pat_fields(&mut self) -> PResult<(Vec<codemap::Spanned<ast::FieldPat>> , bool)> {
+ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>> , bool)> {
let mut fields = Vec::new();
let mut etc = false;
let mut first = true;
return Ok((fields, etc));
}
- fn parse_pat_range_end(&mut self) -> PResult<P<Expr>> {
+ fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
if self.is_path_start() {
let lo = self.span.lo;
let (qself, path) = if try!(self.eat_lt()) {
}
/// Parse a pattern.
- pub fn parse_pat(&mut self) -> PResult<P<Pat>> {
+ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
maybe_whole!(self, NtPat);
let lo = self.span.lo;
/// error message when parsing mistakes like ref foo(a,b)
fn parse_pat_ident(&mut self,
binding_mode: ast::BindingMode)
- -> PResult<ast::Pat_> {
+ -> PResult<'a, ast::Pat_> {
if !self.token.is_plain_ident() {
let span = self.span;
let tok_str = self.this_token_to_string();
}
/// Parse a local variable declaration
- fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<P<Local>> {
+ fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Local>> {
let lo = self.span.lo;
let pat = try!(self.parse_pat());
}
/// Parse a "let" stmt
- fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<P<Decl>> {
+ fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Decl>> {
let lo = self.span.lo;
let local = try!(self.parse_local(attrs));
Ok(P(spanned(lo, self.last_span.hi, DeclLocal(local))))
/// Parse a structure field
fn parse_name_and_ty(&mut self, pr: Visibility,
- attrs: Vec<Attribute> ) -> PResult<StructField> {
+ attrs: Vec<Attribute> ) -> PResult<'a, StructField> {
let lo = match pr {
Inherited => self.span.lo,
Public => self.last_span.lo,
}
/// Parse a statement. may include decl.
- pub fn parse_stmt(&mut self) -> PResult<Option<P<Stmt>>> {
+ pub fn parse_stmt(&mut self) -> PResult<'a, Option<P<Stmt>>> {
Ok(try!(self.parse_stmt_()).map(P))
}
- fn parse_stmt_(&mut self) -> PResult<Option<Stmt>> {
+ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
maybe_whole!(Some deref self, NtStmt);
let attrs = try!(self.parse_outer_attributes());
}
/// Parse a block. No inner attrs are allowed.
- pub fn parse_block(&mut self) -> PResult<P<Block>> {
+ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
maybe_whole!(no_clone self, NtBlock);
let lo = self.span.lo;
}
/// Parse a block. Inner attrs are allowed.
- fn parse_inner_attrs_and_block(&mut self) -> PResult<(Vec<Attribute>, P<Block>)> {
+ fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(pair_empty self, NtBlock);
let lo = self.span.lo;
/// Parse the rest of a block expression or function body
/// Precondition: already parsed the '{'.
- fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<P<Block>> {
+ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<Block>> {
let mut stmts = vec![];
let mut expr = None;
e: P<Expr>,
span: Span,
stmts: &mut Vec<P<Stmt>>,
- last_block_expr: &mut Option<P<Expr>>) -> PResult<()> {
+ last_block_expr: &mut Option<P<Expr>>) -> PResult<'a, ()> {
// expression without semicolon
if classify::expr_requires_semi_to_be_stmt(&*e) {
// Just check for errors and recover; do not eat semicolon yet.
// otherwise returns empty list.
fn parse_colon_then_ty_param_bounds(&mut self,
mode: BoundParsingMode)
- -> PResult<TyParamBounds>
+ -> PResult<'a, TyParamBounds>
{
if !try!(self.eat(&token::Colon) ){
Ok(P::empty())
// and bound = 'region | trait_ref
fn parse_ty_param_bounds(&mut self,
mode: BoundParsingMode)
- -> PResult<TyParamBounds>
+ -> PResult<'a, TyParamBounds>
{
let mut result = vec!();
loop {
}
/// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
- fn parse_ty_param(&mut self) -> PResult<TyParam> {
+ fn parse_ty_param(&mut self) -> PResult<'a, TyParam> {
let span = self.span;
let ident = try!(self.parse_ident());
/// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
/// | ( < lifetimes , typaramseq ( , )? > )
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
- pub fn parse_generics(&mut self) -> PResult<ast::Generics> {
+ pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
maybe_whole!(self, NtGenerics);
if try!(self.eat(&token::Lt) ){
}
}
- fn parse_generic_values_after_lt(&mut self) -> PResult<(Vec<ast::Lifetime>,
+ fn parse_generic_values_after_lt(&mut self) -> PResult<'a, (Vec<ast::Lifetime>,
Vec<P<Ty>>,
Vec<P<TypeBinding>>)> {
let span_lo = self.span.lo;
let msg = format!("expected `,` or `>` after lifetime \
name, found `{}`",
self.this_token_to_string());
- self.span_err(self.span, &msg);
+ let mut err = self.diagnostic().struct_span_err(self.span, &msg);
let span_hi = self.span.hi;
let span_hi = if self.parse_ty().is_ok() {
let msg = format!("did you mean a single argument type &'a Type, \
or did you mean the comma-separated arguments \
'a, Type?");
- self.span_note(mk_sp(span_lo, span_hi), &msg);
+ err.span_note(mk_sp(span_lo, span_hi), &msg);
+ err.emit();
self.abort_if_errors()
}
Ok((lifetimes, types.into_vec(), bindings.into_vec()))
}
- fn forbid_lifetime(&mut self) -> PResult<()> {
+ fn forbid_lifetime(&mut self) -> PResult<'a, ()> {
if self.token.is_lifetime() {
let span = self.span;
return Err(self.span_fatal(span, "lifetime parameters must be declared \
/// ```ignore
/// where T : Trait<U, V> + 'b, 'a : 'b
/// ```
- pub fn parse_where_clause(&mut self) -> PResult<ast::WhereClause> {
+ pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> {
maybe_whole!(self, NtWhereClause);
let mut where_clause = WhereClause {
}
fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
- -> PResult<(Vec<Arg> , bool)> {
+ -> PResult<'a, (Vec<Arg> , bool)> {
let sp = self.span;
let mut args: Vec<Option<Arg>> =
try!(self.parse_unspanned_seq(
}
/// Parse the argument list and result type of a function declaration
- pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<P<FnDecl>> {
+ pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> {
let (args, variadic) = try!(self.parse_fn_args(true, allow_variadic));
let ret_ty = try!(self.parse_ret_ty());
}
}
- fn expect_self_ident(&mut self) -> PResult<ast::Ident> {
+ fn expect_self_ident(&mut self) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(id, token::Plain) if id.name == special_idents::self_.name => {
try!(self.bump());
}
}
- fn expect_self_type_ident(&mut self) -> PResult<ast::Ident> {
+ fn expect_self_type_ident(&mut self) -> PResult<'a, ast::Ident> {
match self.token {
token::Ident(id, token::Plain) if id.name == special_idents::type_self.name => {
try!(self.bump());
/// Parse the argument list and result type of a function
/// that may have a self type.
fn parse_fn_decl_with_self<F>(&mut self,
- parse_arg_fn: F) -> PResult<(ExplicitSelf, P<FnDecl>)> where
- F: FnMut(&mut Parser) -> PResult<Arg>,
+ parse_arg_fn: F) -> PResult<'a, (ExplicitSelf, P<FnDecl>)> where
+ F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
{
- fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
- -> PResult<ast::ExplicitSelf_> {
+ fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
+ -> PResult<'b, ast::ExplicitSelf_> {
// The following things are possible to see here:
//
// fn(&mut self)
}
// parse the |arg, arg| header on a lambda
- fn parse_fn_block_decl(&mut self) -> PResult<P<FnDecl>> {
+ fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> {
let inputs_captures = {
if try!(self.eat(&token::OrOr) ){
Vec::new()
}
/// Parse the name and optional generic types of a function header.
- fn parse_fn_header(&mut self) -> PResult<(Ident, ast::Generics)> {
+ fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> {
let id = try!(self.parse_ident());
let generics = try!(self.parse_generics());
Ok((id, generics))
unsafety: Unsafety,
constness: Constness,
abi: abi::Abi)
- -> PResult<ItemInfo> {
+ -> PResult<'a, ItemInfo> {
let (ident, mut generics) = try!(self.parse_fn_header());
let decl = try!(self.parse_fn_decl(false));
generics.where_clause = try!(self.parse_where_clause());
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
- pub fn parse_fn_front_matter(&mut self) -> PResult<(ast::Constness, ast::Unsafety, abi::Abi)> {
+ pub fn parse_fn_front_matter(&mut self)
+ -> PResult<'a, (ast::Constness, ast::Unsafety, abi::Abi)> {
let is_const_fn = try!(self.eat_keyword(keywords::Const));
let unsafety = try!(self.parse_unsafety());
let (constness, unsafety, abi) = if is_const_fn {
}
/// Parse an impl item.
- pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
+ pub fn parse_impl_item(&mut self) -> PResult<'a, P<ImplItem>> {
maybe_whole!(no_clone self, NtImplItem);
let mut attrs = try!(self.parse_outer_attributes());
fn complain_if_pub_macro(&mut self, visa: Visibility, span: Span) {
match visa {
Public => {
- self.span_err(span, "can't qualify macro invocation with `pub`");
- self.fileline_help(span, "try adjusting the macro to put `pub` inside \
- the invocation");
+ let is_macro_rules: bool = match self.token {
+ token::Ident(sid, _) => sid.name == intern("macro_rules"),
+ _ => false,
+ };
+ if is_macro_rules {
+ self.diagnostic().struct_span_err(span, "can't qualify macro_rules \
+ invocation with `pub`")
+ .fileline_help(span, "did you mean #[macro_export]?")
+ .emit();
+ } else {
+ self.diagnostic().struct_span_err(span, "can't qualify macro \
+ invocation with `pub`")
+ .fileline_help(span, "try adjusting the macro to put `pub` \
+ inside the invocation")
+ .emit();
+ }
}
Inherited => (),
}
/// Parse a method or a macro invocation in a trait impl.
fn parse_impl_method(&mut self, vis: Visibility)
- -> PResult<(Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
+ -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not)
}
/// Parse trait Foo { ... }
- fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<ItemInfo> {
+ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
let ident = try!(self.parse_ident());
let mut tps = try!(self.parse_generics());
/// impl<T> Foo { ... }
/// impl<T> ToString for &'static T { ... }
/// impl Send for .. {}
- fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<ItemInfo> {
+ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> {
let impl_span = self.span;
// First, parse type parameters if necessary.
}
/// Parse a::B<String,i32>
- fn parse_trait_ref(&mut self) -> PResult<TraitRef> {
+ fn parse_trait_ref(&mut self) -> PResult<'a, TraitRef> {
Ok(ast::TraitRef {
path: try!(self.parse_path(LifetimeAndTypesWithoutColons)),
ref_id: ast::DUMMY_NODE_ID,
})
}
- fn parse_late_bound_lifetime_defs(&mut self) -> PResult<Vec<ast::LifetimeDef>> {
+ fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> {
if try!(self.eat_keyword(keywords::For) ){
try!(self.expect(&token::Lt));
let lifetime_defs = try!(self.parse_lifetime_defs());
}
/// Parse for<'l> a::B<String,i32>
- fn parse_poly_trait_ref(&mut self) -> PResult<PolyTraitRef> {
+ fn parse_poly_trait_ref(&mut self) -> PResult<'a, PolyTraitRef> {
let lo = self.span.lo;
let lifetime_defs = try!(self.parse_late_bound_lifetime_defs());
}
/// Parse struct Foo { ... }
- fn parse_item_struct(&mut self) -> PResult<ItemInfo> {
+ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
let class_name = try!(self.parse_ident());
let mut generics = try!(self.parse_generics());
Ok((class_name, ItemStruct(vdata, generics), None))
}
- pub fn parse_record_struct_body(&mut self, parse_pub: ParsePub) -> PResult<Vec<StructField>> {
+ pub fn parse_record_struct_body(&mut self,
+ parse_pub: ParsePub)
+ -> PResult<'a, Vec<StructField>> {
let mut fields = Vec::new();
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
while self.token != token::CloseDelim(token::Brace) {
Ok(fields)
}
- pub fn parse_tuple_struct_body(&mut self, parse_pub: ParsePub) -> PResult<Vec<StructField>> {
+ pub fn parse_tuple_struct_body(&mut self,
+ parse_pub: ParsePub)
+ -> PResult<'a, Vec<StructField>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
// Unit like structs are handled in parse_item_struct function
let fields = try!(self.parse_unspanned_seq(
pub fn parse_single_struct_field(&mut self,
vis: Visibility,
attrs: Vec<Attribute> )
- -> PResult<StructField> {
+ -> PResult<'a, StructField> {
let a_var = try!(self.parse_name_and_ty(vis, attrs));
match self.token {
token::Comma => {
}
/// Parse an element of a struct definition
- fn parse_struct_decl_field(&mut self, parse_pub: ParsePub) -> PResult<StructField> {
+ fn parse_struct_decl_field(&mut self, parse_pub: ParsePub) -> PResult<'a, StructField> {
let attrs = try!(self.parse_outer_attributes());
}
/// Parse visibility: PUB or nothing
- fn parse_visibility(&mut self) -> PResult<Visibility> {
+ fn parse_visibility(&mut self) -> PResult<'a, Visibility> {
if try!(self.eat_keyword(keywords::Pub)) { Ok(Public) }
else { Ok(Inherited) }
}
/// Given a termination token, parse all of the items in a module
- fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> PResult<Mod> {
+ fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> PResult<'a, Mod> {
let mut items = vec![];
while let Some(item) = try!(self.parse_item()) {
items.push(item);
})
}
- fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<ItemInfo> {
+ fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
let id = try!(self.parse_ident());
try!(self.expect(&token::Colon));
let ty = try!(self.parse_ty_sum());
}
/// Parse a `mod <foo> { ... }` or `mod <foo>;` item
- fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<ItemInfo> {
+ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
let id_span = self.span;
let id = try!(self.parse_ident());
if self.check(&token::Semi) {
fn submod_path(&mut self,
id: ast::Ident,
outer_attrs: &[ast::Attribute],
- id_sp: Span) -> PResult<ModulePathSuccess> {
+ id_sp: Span) -> PResult<'a, ModulePathSuccess> {
let mut prefix = PathBuf::from(&self.sess.codemap().span_to_filename(self.span));
prefix.pop();
let mut dir_path = prefix;
let paths = Parser::default_submod_path(id, &dir_path, self.sess.codemap());
if !self.owns_directory {
- self.span_err(id_sp, "cannot declare a new module at this location");
+ let mut err = self.diagnostic().struct_span_err(id_sp,
+ "cannot declare a new module at this location");
let this_module = match self.mod_path_stack.last() {
Some(name) => name.to_string(),
None => self.root_module_name.as_ref().unwrap().clone(),
};
- self.span_note(id_sp,
- &format!("maybe move this module `{0}` to its own directory \
+ err.span_note(id_sp,
+ &format!("maybe move this module `{0}` to its own directory \
via `{0}/mod.rs`",
this_module));
if paths.path_exists {
- self.span_note(id_sp,
- &format!("... or maybe `use` the module `{}` instead \
- of possibly redeclaring it",
- paths.name));
+ err.span_note(id_sp,
+ &format!("... or maybe `use` the module `{}` instead \
+ of possibly redeclaring it",
+ paths.name));
}
+ err.emit();
self.abort_if_errors();
}
id: ast::Ident,
outer_attrs: &[ast::Attribute],
id_sp: Span)
- -> PResult<(ast::Item_, Vec<ast::Attribute> )> {
+ -> PResult<'a, (ast::Item_, Vec<ast::Attribute> )> {
let ModulePathSuccess { path, owns_directory } = try!(self.submod_path(id,
outer_attrs,
id_sp));
path: PathBuf,
owns_directory: bool,
name: String,
- id_sp: Span) -> PResult<(ast::Item_, Vec<ast::Attribute> )> {
+ id_sp: Span) -> PResult<'a, (ast::Item_, Vec<ast::Attribute> )> {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
match included_mod_stack.iter().position(|p| *p == path) {
Some(i) => {
/// Parse a function declaration from a foreign module
fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: BytePos,
- attrs: Vec<Attribute>) -> PResult<P<ForeignItem>> {
+ attrs: Vec<Attribute>) -> PResult<'a, P<ForeignItem>> {
try!(self.expect_keyword(keywords::Fn));
let (ident, mut generics) = try!(self.parse_fn_header());
/// Parse a static item from a foreign module
fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: BytePos,
- attrs: Vec<Attribute>) -> PResult<P<ForeignItem>> {
+ attrs: Vec<Attribute>) -> PResult<'a, P<ForeignItem>> {
try!(self.expect_keyword(keywords::Static));
let mutbl = try!(self.eat_keyword(keywords::Mut));
lo: BytePos,
visibility: Visibility,
attrs: Vec<Attribute>)
- -> PResult<P<Item>> {
+ -> PResult<'a, P<Item>> {
let crate_name = try!(self.parse_ident());
let (maybe_path, ident) = if let Some(ident) = try!(self.parse_rename()) {
opt_abi: Option<abi::Abi>,
visibility: Visibility,
mut attrs: Vec<Attribute>)
- -> PResult<P<Item>> {
+ -> PResult<'a, P<Item>> {
try!(self.expect(&token::OpenDelim(token::Brace)));
let abi = opt_abi.unwrap_or(abi::C);
}
/// Parse type Foo = Bar;
- fn parse_item_type(&mut self) -> PResult<ItemInfo> {
+ fn parse_item_type(&mut self) -> PResult<'a, ItemInfo> {
let ident = try!(self.parse_ident());
let mut tps = try!(self.parse_generics());
tps.where_clause = try!(self.parse_where_clause());
}
/// Parse the part of an "enum" decl following the '{'
- fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<EnumDef> {
+ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
let mut variants = Vec::new();
let mut all_nullary = true;
let mut any_disr = None;
}
/// Parse an "enum" declaration
- fn parse_item_enum(&mut self) -> PResult<ItemInfo> {
+ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
let id = try!(self.parse_ident());
let mut generics = try!(self.parse_generics());
generics.where_clause = try!(self.parse_where_clause());
/// Parses a string as an ABI spec on an extern type or module. Consumes
/// the `extern` keyword, if one is found.
- fn parse_opt_abi(&mut self) -> PResult<Option<abi::Abi>> {
+ fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
match self.token {
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
let sp = self.span;
/// NB: this function no longer parses the items inside an
/// extern crate.
fn parse_item_(&mut self, attrs: Vec<Attribute>,
- macros_allowed: bool, attributes_allowed: bool) -> PResult<Option<P<Item>>> {
+ macros_allowed: bool, attributes_allowed: bool) -> PResult<'a, Option<P<Item>>> {
let nt_item = match self.token {
token::Interpolated(token::NtItem(ref item)) => {
Some((**item).clone())
// CONST ITEM
if try!(self.eat_keyword(keywords::Mut) ){
let last_span = self.last_span;
- self.span_err(last_span, "const globals cannot be mutable");
- self.fileline_help(last_span, "did you mean to declare a static?");
+ self.diagnostic().struct_span_err(last_span, "const globals cannot be mutable")
+ .fileline_help(last_span, "did you mean to declare a static?")
+ .emit();
}
let (ident, item_, extra_attrs) = try!(self.parse_item_const(None));
let last_span = self.last_span;
}
/// Parse a foreign item.
- fn parse_foreign_item(&mut self) -> PResult<Option<P<ForeignItem>>> {
+ fn parse_foreign_item(&mut self) -> PResult<'a, Option<P<ForeignItem>>> {
let attrs = try!(self.parse_outer_attributes());
let lo = self.span.lo;
let visibility = try!(self.parse_visibility());
attributes_allowed: bool,
lo: BytePos,
visibility: Visibility
- ) -> PResult<Option<P<Item>>> {
+ ) -> PResult<'a, Option<P<Item>>> {
if macros_allowed && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not)
&& (self.look_ahead(2, |t| t.is_plain_ident())
Ok(None)
}
- pub fn parse_item(&mut self) -> PResult<Option<P<Item>>> {
+ pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
let attrs = try!(self.parse_outer_attributes());
self.parse_item_(attrs, true, false)
}
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
/// | MOD? non_global_path MOD_SEP STAR
/// | MOD? non_global_path
- fn parse_view_path(&mut self) -> PResult<P<ViewPath>> {
+ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
let lo = self.span.lo;
// Allow a leading :: because the paths are absolute either way.
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
}
- fn parse_rename(&mut self) -> PResult<Option<Ident>> {
+ fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
if try!(self.eat_keyword(keywords::As)) {
self.parse_ident().map(Some)
} else {
/// Parses a source module as a crate. This is the main
/// entry point for the parser.
- pub fn parse_crate_mod(&mut self) -> PResult<Crate> {
+ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
let lo = self.span.lo;
Ok(ast::Crate {
attrs: try!(self.parse_inner_attributes()),
}
pub fn parse_optional_str(&mut self)
- -> PResult<Option<(InternedString,
+ -> PResult<'a, Option<(InternedString,
ast::StrStyle,
Option<ast::Name>)>> {
let ret = match self.token {
Ok(Some(ret))
}
- pub fn parse_str(&mut self) -> PResult<(InternedString, StrStyle)> {
+ pub fn parse_str(&mut self) -> PResult<'a, (InternedString, StrStyle)> {
match try!(self.parse_optional_str()) {
Some((s, style, suf)) => {
let sp = self.last_span;
}
match *parameters {
- ast::AngleBracketedParameters(ref data) => {
+ ast::PathParameters::AngleBracketed(ref data) => {
try!(word(&mut self.s, "<"));
let mut comma = false;
try!(word(&mut self.s, ">"))
}
- ast::ParenthesizedParameters(ref data) => {
+ ast::PathParameters::Parenthesized(ref data) => {
try!(word(&mut self.s, "("));
try!(self.commasep(
Inconsistent,
impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> {
fn visit_expr(&mut self, e: &ast::Expr) {
if let Mode::Expression = self.mode {
- self.span_diagnostic.span_note(e.span, "expression");
+ self.span_diagnostic.span_warn(e.span, "expression");
}
visit::walk_expr(self, e);
}
fn visit_pat(&mut self, p: &ast::Pat) {
if let Mode::Pattern = self.mode {
- self.span_diagnostic.span_note(p.span, "pattern");
+ self.span_diagnostic.span_warn(p.span, "pattern");
}
visit::walk_pat(self, p);
}
fn visit_ty(&mut self, t: &ast::Ty) {
if let Mode::Type = self.mode {
- self.span_diagnostic.span_note(t.span, "type");
+ self.span_diagnostic.span_warn(t.span, "type");
}
visit::walk_ty(self, t);
}
source_str)
}
-fn with_error_checking_parse<T, F>(s: String, f: F) -> T where
- F: FnOnce(&mut Parser) -> PResult<T>,
+fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T where
+ F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
{
- let ps = ParseSess::new();
let mut p = string_to_parser(&ps, s);
let x = panictry!(f(&mut p));
p.abort_if_errors();
/// Parse a string, return a crate.
pub fn string_to_crate (source_str : String) -> ast::Crate {
- with_error_checking_parse(source_str, |p| {
+ let ps = ParseSess::new();
+ with_error_checking_parse(source_str, &ps, |p| {
p.parse_crate_mod()
})
}
/// Parse a string, return an expr
pub fn string_to_expr (source_str : String) -> P<ast::Expr> {
- with_error_checking_parse(source_str, |p| {
+ let ps = ParseSess::new();
+ with_error_checking_parse(source_str, &ps, |p| {
p.parse_expr()
})
}
/// Parse a string, return an item
pub fn string_to_item (source_str : String) -> Option<P<ast::Item>> {
- with_error_checking_parse(source_str, |p| {
+ let ps = ParseSess::new();
+ with_error_checking_parse(source_str, &ps, |p| {
p.parse_item()
})
}
/// Parse a string, return a stmt
pub fn string_to_stmt(source_str : String) -> Option<P<ast::Stmt>> {
- with_error_checking_parse(source_str, |p| {
+ let ps = ParseSess::new();
+ with_error_checking_parse(source_str, &ps, |p| {
p.parse_stmt()
})
}
/// Parse a string, return a pat. Uses "irrefutable"... which doesn't
/// (currently) affect parsing.
pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
- with_error_checking_parse(source_str, |p| {
+ let ps = ParseSess::new();
+ with_error_checking_parse(source_str, &ps, |p| {
p.parse_pat()
})
}
_path_span: Span,
path_parameters: &'v PathParameters) {
match *path_parameters {
- AngleBracketedParameters(ref data) => {
+ PathParameters::AngleBracketed(ref data) => {
walk_list!(visitor, visit_ty, &data.types);
walk_list!(visitor, visit_lifetime, &data.lifetimes);
walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
}
- ParenthesizedParameters(ref data) => {
+ PathParameters::Parenthesized(ref data) => {
walk_list!(visitor, visit_ty, &data.inputs);
walk_list!(visitor, visit_ty, &data.output);
}
match names.get(name) {
None => {}
Some(prev) => {
- ecx.span_err(e.span,
- &format!("duplicate argument named `{}`",
- name));
- ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here");
+ ecx.struct_span_err(e.span,
+ &format!("duplicate argument named `{}`",
+ name))
+ .span_note(prev.span, "previously here")
+ .emit();
continue
}
}
#![feature(str_char)]
extern crate fmt_macros;
+#[macro_use]
extern crate syntax;
use syntax::ext::base::{MacroExpanderFn, NormalTT};
use syntax::ext::base::{SyntaxEnv, SyntaxExtension};
use syntax::parse::token::intern;
-// A variant of 'try!' that panics on Err(FatalError). This is used as a
-// crutch on the way towards a non-panic!-prone parser. It should be used
-// for fatal parsing errors; eventually we plan to convert all code using
-// panictry to just use normal try
-macro_rules! panictry {
- ($e:expr) => ({
- use std::result::Result::{Ok, Err};
- use syntax::errors::FatalError;
- match $e {
- Ok(e) => e,
- Err(FatalError) => panic!(FatalError)
- }
- })
-}
mod asm;
mod cfg;
S 2015-12-18 3391630
+ bitrig-x86_64 6476e1562df02389b55553b4c88b1f4fd121cd40
+ freebsd-i386 7e624c50494402e1feb14c743d659fbd71b448f5
+ freebsd-x86_64 91724d4e655807a2a2e940ac50992ebeaac16ea9
linux-i386 a09c4a4036151d0cb28e265101669731600e01f2
linux-x86_64 97e2a5eb8904962df8596e95d6e5d9b574d73bf4
macos-i386 ca52d2d3ba6497ed007705ee3401cf7efc136ca1
+++ /dev/null
-// Copyright 2015 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.
-
-// Issue #14660
-
-macro_rules! priv_x { () => {
- static x: u32 = 0;
-}}
-
-macro_rules! pub_x { () => {
- pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub`
- //~^ HELP try adjusting the macro to put `pub` inside the invocation
-}}
-
-mod foo {
- pub_x!();
-}
-
-fn main() {
- let y: u32 = foo::x;
-}
+++ /dev/null
-// Copyright 2015 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.
-
-// Issue #18317
-
-mod bleh {
- macro_rules! defn {
- ($n:ident) => (
- fn $n (&self) -> i32 {
- println!("{}", stringify!($n));
- 1
- }
- )
- }
-
- #[derive(Copy, Clone)]
- pub struct S;
-
- impl S {
- pub defn!(f); //~ ERROR can't qualify macro invocation with `pub`
- //~^ HELP try adjusting the macro to put `pub` inside the invocation
- }
-}
-
-fn main() {
- bleh::S.f();
-}
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-fn that_odd_parse() {
- // see assoc-oddities-1 for explanation
- x + if c { a } else { b }[n]; //~ ERROR expected one of
-}
--- /dev/null
+// Copyright 2015 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.
+
+// Issue #14660
+
+macro_rules! priv_x { () => {
+ static x: u32 = 0;
+}}
+
+macro_rules! pub_x { () => {
+ pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub`
+ //~^ HELP try adjusting the macro to put `pub` inside the invocation
+}}
+
+mod foo {
+ pub_x!();
+}
+
+fn main() {
+ let y: u32 = foo::x;
+}
--- /dev/null
+// Copyright 2015 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.
+
+#[macro_use] mod bleh {
+ pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation with `pub`
+ //~^ HELP did you mean #[macro_export]?
+ ($n:ident) => (
+ fn $n () -> i32 {
+ 1
+ }
+ )
+ }
+
+}
+
+foo!(meh);
+
+fn main() {
+ println!("{}", meh());
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Issue #18317
+
+mod bleh {
+ macro_rules! defn {
+ ($n:ident) => (
+ fn $n (&self) -> i32 {
+ println!("{}", stringify!($n));
+ 1
+ }
+ )
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct S;
+
+ impl S {
+ pub defn!(f); //~ ERROR can't qualify macro invocation with `pub`
+ //~^ HELP try adjusting the macro to put `pub` inside the invocation
+ }
+}
+
+fn main() {
+ bleh::S.f();
+}
source_str)
}
-fn with_error_checking_parse<T, F>(s: String, f: F) -> PResult<T> where
- F: FnOnce(&mut Parser) -> PResult<T>,
+fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where
+ F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
{
- let ps = ParseSess::new();
let mut p = string_to_parser(&ps, s);
let x = f(&mut p);
if ps.span_diagnostic.has_errors() || p.token != token::Eof {
+ if let Err(mut e) = x {
+ e.cancel();
+ }
return Err(p.fatal("parse error"));
}
x
}
-fn expr(s: &str) -> PResult<P<ast::Expr>> {
- with_error_checking_parse(s.to_string(), |p| {
+fn expr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Expr>> {
+ with_error_checking_parse(s.to_string(), ps, |p| {
p.parse_expr()
})
}
-fn stmt(s: &str) -> PResult<P<ast::Stmt>> {
- with_error_checking_parse(s.to_string(), |p| {
+fn stmt<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Stmt>> {
+ with_error_checking_parse(s.to_string(), ps, |p| {
p.parse_stmt().map(|s| s.unwrap())
})
}
-fn attr(s: &str) -> PResult<ast::Attribute> {
- with_error_checking_parse(s.to_string(), |p| {
+fn attr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Attribute> {
+ with_error_checking_parse(s.to_string(), ps, |p| {
p.parse_attribute(true)
})
}
}
fn check_expr_attrs(es: &str, expected: &[&str]) {
- let e = expr(es).expect("parse error");
+ let ps = ParseSess::new();
+ let e = expr(es, &ps).expect("parse error");
let actual = &e.attrs;
str_compare(es,
- &expected.iter().map(|r| attr(r).unwrap()).collect::<Vec<_>>(),
+ &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
actual.as_attr_slice(),
pprust::attribute_to_string);
}
fn check_stmt_attrs(es: &str, expected: &[&str]) {
- let e = stmt(es).expect("parse error");
+ let ps = ParseSess::new();
+ let e = stmt(es, &ps).expect("parse error");
let actual = e.node.attrs();
str_compare(es,
- &expected.iter().map(|r| attr(r).unwrap()).collect::<Vec<_>>(),
+ &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
actual,
pprust::attribute_to_string);
}
fn reject_expr_parse(es: &str) {
- assert!(expr(es).is_err(), "parser did not reject `{}`", es);
+ let ps = ParseSess::new();
+ match expr(es, &ps) {
+ Ok(_) => panic!("parser did not reject `{}`", es),
+ Err(mut e) => e.cancel(),
+ };
}
fn reject_stmt_parse(es: &str) {
- assert!(stmt(es).is_err(), "parser did not reject `{}`", es);
+ let ps = ParseSess::new();
+ match stmt(es, &ps) {
+ Ok(_) => panic!("parser did not reject `{}`", es),
+ Err(mut e) => e.cancel(),
+ };
}
fn main() {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn that_odd_parse(c: bool, n: usize) -> u32 {
+ let x = 2;
+ let a = [1, 2, 3, 4];
+ let b = [5, 6, 7, 7];
+ x + if c { a } else { b }[n]
+}
+
+fn main() {
+ assert_eq!(4, that_odd_parse(true, 1));
+ assert_eq!(8, that_odd_parse(false, 1));
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let v1 = { 1 + {2} * {3} };
+ let v2 = 1 + {2} * {3} ;
+
+ assert_eq!(7, v1);
+ assert_eq!(7, v2);
+
+ let v3;
+ v3 = { 1 + {2} * {3} };
+ let v4;
+ v4 = 1 + {2} * {3};
+ assert_eq!(7, v3);
+ assert_eq!(7, v4);
+
+ let v5 = { 1 + {2} * 3 };
+ assert_eq!(7, v5);
+
+ let v9 = { 1 + if 1 > 2 {1} else {2} * {3} };
+ assert_eq!(7, v9);
+}
--- /dev/null
+// Copyright 2015 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(libc, rustc_attrs)]
+
+extern crate libc;
+
+fn func(){}
+
+const STR: &'static str = "hello";
+const BSTR: &'static [u8; 5] = b"hello";
+
+#[rustc_mir]
+fn from_ptr()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, *const ()) {
+ let f = 1_usize as *const libc::FILE;
+ let c1 = f as isize;
+ let c2 = f as usize;
+ let c3 = f as i8;
+ let c4 = f as i16;
+ let c5 = f as i32;
+ let c6 = f as i64;
+ let c7 = f as u8;
+ let c8 = f as u16;
+ let c9 = f as u32;
+ let c10 = f as u64;
+ let c11 = f as *const ();
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)
+}
+
+#[rustc_mir]
+fn from_1()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1 as isize;
+ let c2 = 1 as usize;
+ let c3 = 1 as i8;
+ let c4 = 1 as i16;
+ let c5 = 1 as i32;
+ let c6 = 1 as i64;
+ let c7 = 1 as u8;
+ let c8 = 1 as u16;
+ let c9 = 1 as u32;
+ let c10 = 1 as u64;
+ let c11 = 1 as f32;
+ let c12 = 1 as f64;
+ let c13 = 1 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1usize()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_usize as isize;
+ let c2 = 1_usize as usize;
+ let c3 = 1_usize as i8;
+ let c4 = 1_usize as i16;
+ let c5 = 1_usize as i32;
+ let c6 = 1_usize as i64;
+ let c7 = 1_usize as u8;
+ let c8 = 1_usize as u16;
+ let c9 = 1_usize as u32;
+ let c10 = 1_usize as u64;
+ let c11 = 1_usize as f32;
+ let c12 = 1_usize as f64;
+ let c13 = 1_usize as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1isize()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_isize as isize;
+ let c2 = 1_isize as usize;
+ let c3 = 1_isize as i8;
+ let c4 = 1_isize as i16;
+ let c5 = 1_isize as i32;
+ let c6 = 1_isize as i64;
+ let c7 = 1_isize as u8;
+ let c8 = 1_isize as u16;
+ let c9 = 1_isize as u32;
+ let c10 = 1_isize as u64;
+ let c11 = 1_isize as f32;
+ let c12 = 1_isize as f64;
+ let c13 = 1_isize as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u8()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_u8 as isize;
+ let c2 = 1_u8 as usize;
+ let c3 = 1_u8 as i8;
+ let c4 = 1_u8 as i16;
+ let c5 = 1_u8 as i32;
+ let c6 = 1_u8 as i64;
+ let c7 = 1_u8 as u8;
+ let c8 = 1_u8 as u16;
+ let c9 = 1_u8 as u32;
+ let c10 = 1_u8 as u64;
+ let c11 = 1_u8 as f32;
+ let c12 = 1_u8 as f64;
+ let c13 = 1_u8 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i8()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_i8 as isize;
+ let c2 = 1_i8 as usize;
+ let c3 = 1_i8 as i8;
+ let c4 = 1_i8 as i16;
+ let c5 = 1_i8 as i32;
+ let c6 = 1_i8 as i64;
+ let c7 = 1_i8 as u8;
+ let c8 = 1_i8 as u16;
+ let c9 = 1_i8 as u32;
+ let c10 = 1_i8 as u64;
+ let c11 = 1_i8 as f32;
+ let c12 = 1_i8 as f64;
+ let c13 = 1_i8 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u16()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_u16 as isize;
+ let c2 = 1_u16 as usize;
+ let c3 = 1_u16 as i8;
+ let c4 = 1_u16 as i16;
+ let c5 = 1_u16 as i32;
+ let c6 = 1_u16 as i64;
+ let c7 = 1_u16 as u8;
+ let c8 = 1_u16 as u16;
+ let c9 = 1_u16 as u32;
+ let c10 = 1_u16 as u64;
+ let c11 = 1_u16 as f32;
+ let c12 = 1_u16 as f64;
+ let c13 = 1_u16 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i16()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_i16 as isize;
+ let c2 = 1_i16 as usize;
+ let c3 = 1_i16 as i8;
+ let c4 = 1_i16 as i16;
+ let c5 = 1_i16 as i32;
+ let c6 = 1_i16 as i64;
+ let c7 = 1_i16 as u8;
+ let c8 = 1_i16 as u16;
+ let c9 = 1_i16 as u32;
+ let c10 = 1_i16 as u64;
+ let c11 = 1_i16 as f32;
+ let c12 = 1_i16 as f64;
+ let c13 = 1_i16 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_u32 as isize;
+ let c2 = 1_u32 as usize;
+ let c3 = 1_u32 as i8;
+ let c4 = 1_u32 as i16;
+ let c5 = 1_u32 as i32;
+ let c6 = 1_u32 as i64;
+ let c7 = 1_u32 as u8;
+ let c8 = 1_u32 as u16;
+ let c9 = 1_u32 as u32;
+ let c10 = 1_u32 as u64;
+ let c11 = 1_u32 as f32;
+ let c12 = 1_u32 as f64;
+ let c13 = 1_u32 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_i32 as isize;
+ let c2 = 1_i32 as usize;
+ let c3 = 1_i32 as i8;
+ let c4 = 1_i32 as i16;
+ let c5 = 1_i32 as i32;
+ let c6 = 1_i32 as i64;
+ let c7 = 1_i32 as u8;
+ let c8 = 1_i32 as u16;
+ let c9 = 1_i32 as u32;
+ let c10 = 1_i32 as u64;
+ let c11 = 1_i32 as f32;
+ let c12 = 1_i32 as f64;
+ let c13 = 1_i32 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_u64 as isize;
+ let c2 = 1_u64 as usize;
+ let c3 = 1_u64 as i8;
+ let c4 = 1_u64 as i16;
+ let c5 = 1_u64 as i32;
+ let c6 = 1_u64 as i64;
+ let c7 = 1_u64 as u8;
+ let c8 = 1_u64 as u16;
+ let c9 = 1_u64 as u32;
+ let c10 = 1_u64 as u64;
+ let c11 = 1_u64 as f32;
+ let c12 = 1_u64 as f64;
+ let c13 = 1_u64 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+ let c1 = 1_i64 as isize;
+ let c2 = 1_i64 as usize;
+ let c3 = 1_i64 as i8;
+ let c4 = 1_i64 as i16;
+ let c5 = 1_i64 as i32;
+ let c6 = 1_i64 as i64;
+ let c7 = 1_i64 as u8;
+ let c8 = 1_i64 as u16;
+ let c9 = 1_i64 as u32;
+ let c10 = 1_i64 as u64;
+ let c11 = 1_i64 as f32;
+ let c12 = 1_i64 as f64;
+ let c13 = 1_i64 as *const libc::FILE;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_bool()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64) {
+ let c1 = true as isize;
+ let c2 = true as usize;
+ let c3 = true as i8;
+ let c4 = true as i16;
+ let c5 = true as i32;
+ let c6 = true as i64;
+ let c7 = true as u8;
+ let c8 = true as u16;
+ let c9 = true as u32;
+ let c10 = true as u64;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)
+}
+
+#[rustc_mir]
+fn from_1f32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) {
+ let c1 = 1.0_f32 as isize;
+ let c2 = 1.0_f32 as usize;
+ let c3 = 1.0_f32 as i8;
+ let c4 = 1.0_f32 as i16;
+ let c5 = 1.0_f32 as i32;
+ let c6 = 1.0_f32 as i64;
+ let c7 = 1.0_f32 as u8;
+ let c8 = 1.0_f32 as u16;
+ let c9 = 1.0_f32 as u32;
+ let c10 = 1.0_f32 as u64;
+ let c11 = 1.0_f32 as f32;
+ let c12 = 1.0_f32 as f64;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)
+}
+
+#[rustc_mir]
+fn from_1f64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) {
+ let c1 = 1.0f64 as isize;
+ let c2 = 1.0f64 as usize;
+ let c3 = 1.0f64 as i8;
+ let c4 = 1.0f64 as i16;
+ let c5 = 1.0f64 as i32;
+ let c6 = 1.0f64 as i64;
+ let c7 = 1.0f64 as u8;
+ let c8 = 1.0f64 as u16;
+ let c9 = 1.0f64 as u32;
+ let c10 = 1.0f64 as u64;
+ let c11 = 1.0f64 as f32;
+ let c12 = 1.0f64 as f64;
+ (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)
+}
+
+#[rustc_mir]
+fn other_casts()
+-> (*const u8, *const isize, *const u8, *const u8) {
+ let c1 = func as *const u8;
+ let c2 = c1 as *const isize;
+
+ let r = &42u32;
+ let _ = r as *const u32;
+
+ // fat-ptr -> fat-ptr -> fat-raw-ptr -> thin-ptr
+ let c3 = STR as &str as *const str as *const u8;
+
+ let c4 = BSTR as *const [u8] as *const [u16] as *const u8;
+ (c1, c2, c3, c4)
+}
+
+pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8,
+ u16, u32, u64, f32, f64, *const libc::FILE),
+ r: (isize, usize, i8, i16, i32, i64, u8,
+ u16, u32, u64, f32, f64, *const libc::FILE)) -> bool {
+ let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = l;
+ let (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13) = r;
+ l1 == r1 && l2 == r2 && l3 == r3 && l4 == r4 && l5 == r5 && l6 == r6 && l7 == r7 &&
+ l8 == r8 && l9 == r9 && l10 == r10 && l11 == r11 && l12 == r12 && l13 == r13
+}
+
+
+pub fn main() {
+ let f = 1_usize as *const libc::FILE;
+ let t13 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0, f);
+ let t12 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0);
+ assert_eq_13(from_1(), t13);
+ assert_eq_13(from_1usize(), t13);
+ assert_eq_13(from_1isize(), t13);
+ assert_eq_13(from_1u8(), t13);
+ assert_eq_13(from_1i8(), t13);
+ assert_eq_13(from_1u16(), t13);
+ assert_eq_13(from_1i16(), t13);
+ assert_eq_13(from_1u32(), t13);
+ assert_eq_13(from_1i32(), t13);
+ assert_eq_13(from_1u64(), t13);
+ assert_eq_13(from_1i64(), t13);
+ assert_eq!(from_1f32(), t12);
+ assert_eq!(from_1f64(), t12);
+
+ assert_eq!(from_ptr(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 as *const ()));
+ assert_eq!(from_bool(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
+
+ assert_eq!(other_casts(), (func as *const u8, func as *const isize,
+ STR as *const str as *const u8, BSTR as *const [u8] as *const u8));
+}