use infer::error_reporting::nice_region_error::NiceRegionError;
use ty;
use util::common::ErrorReported;
+ use errors::Applicability;
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
// version new_ty of its type where the anonymous region is replaced
// with the named one.//scope_def_id
let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
- && self.is_suitable_region(sup).is_some()
+ && self.tcx.is_suitable_region(sup).is_some()
&& self.find_arg_with_region(sup, sub).is_some()
{
(
sub,
sup,
self.find_arg_with_region(sup, sub).unwrap(),
- self.is_suitable_region(sup).unwrap(),
+ self.tcx.is_suitable_region(sup).unwrap(),
)
- } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some()
+ } else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some()
&& self.find_arg_with_region(sub, sup).is_some()
{
(
sup,
sub,
self.find_arg_with_region(sub, sup).unwrap(),
- self.is_suitable_region(sub).unwrap(),
+ self.tcx.is_suitable_region(sub).unwrap(),
)
} else {
return None; // inapplicable
E0621,
"explicit lifetime required in {}",
error_var
- ).span_suggestion(
+ ).span_suggestion_with_applicability(
new_ty_span,
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
- new_ty.to_string()
+ new_ty.to_string(),
+ Applicability::Unspecified,
)
- .span_label(span, format!("lifetime `{}` required", named))
- .emit();
+ .span_label(span, format!("lifetime `{}` required", named))
+ .emit();
return Some(ErrorReported);
}
use infer::lexical_region_resolve::RegionResolutionError;
use ty::{BoundRegion, FreeRegion, RegionKind};
use util::common::ErrorReported;
+ use errors::Applicability;
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static impl Trait.
sup_origin,
sup_r,
) => {
- let anon_reg_sup = self.is_suitable_region(sup_r)?;
+ let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
if sub_r == &RegionKind::ReStatic &&
- self.is_return_type_impl_trait(anon_reg_sup.def_id)
+ self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some()
{
let sp = var_origin.span();
let return_sp = sub_origin.span();
_ => "'_".to_owned(),
};
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
return_sp,
&format!(
"you can add a constraint to the return type to make it last \
lifetime,
),
format!("{} + {}", snippet, lifetime_name),
+ Applicability::Unspecified,
);
}
err.emit();
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
use syntax::ast::NodeId;
- use errors::{self, DiagnosticBuilder, DiagnosticId};
+ use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
use errors::emitter::{Emitter, EmitterWriter};
use syntax::edition::Edition;
use syntax::json::JsonEmitter;
diag_builder.span_note(span, message);
}
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
- let span = span_maybe.expect("span_suggestion needs a span");
- diag_builder.span_suggestion(span, message, suggestion);
+ let span = span_maybe.expect("span_suggestion_* needs a span");
+ diag_builder.span_suggestion_with_applicability(
+ span,
+ message,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
}
}
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
+ let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics;
let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
can_emit_warnings,
treat_err_as_bug,
report_delayed_bugs,
+ dont_buffer_diagnostics,
external_macro_backtrace,
..Default::default()
},
LpUpvar(upvar_id) => {
let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
let hir_id = bccx.tcx.hir.node_to_hir_id(block_id);
- region::Scope::Node(hir_id.local_id)
+ region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }
}
LpDowncast(ref base, _) |
LpExtend(ref base, ..) => base.kill_scope(bccx),
}) = cmt.cat {
db.note(fn_closure_msg);
} else {
- db.span_suggestion(sp, msg, suggestion);
+ db.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
} else {
- db.span_suggestion(sp, msg, suggestion);
+ db.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
}
_ => {
let let_span = self.tcx.hir.span(node_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
if let Some(replace_str) = suggestion {
- db.span_suggestion(
+ db.span_suggestion_with_applicability(
let_span,
"use a mutable reference instead",
replace_str,
+ // I believe this can be machine applicable,
+ // but if there are multiple attempted uses of an immutable
+ // reference, I don't know how rustfix handles it, it might
+ // attempt fixing them multiple times.
+ // @estebank
+ Applicability::Unspecified,
);
}
}
)) = ty.map(|t| &t.node)
{
let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id);
- db.span_suggestion(
+ db.span_suggestion_with_applicability(
self.tcx.hir.span(borrow_expr_id),
"consider removing the `&mut`, as it is an \
immutable binding to a mutable reference",
- snippet
+ snippet,
+ Applicability::MachineApplicable,
);
} else {
db.span_suggestion_with_applicability(
&cmt_path_or_string,
capture_span,
Origin::Ast)
- .span_suggestion(err.span,
- &format!("to force the closure to take ownership of {} \
- (and any other referenced variables), \
- use the `move` keyword",
- cmt_path_or_string),
- suggestion)
+ .span_suggestion_with_applicability(
+ err.span,
+ &format!("to force the closure to take ownership of {} \
+ (and any other referenced variables), \
+ use the `move` keyword",
+ cmt_path_or_string),
+ suggestion,
+ Applicability::MachineApplicable,
+ )
.emit();
self.signal_error();
}
use syntax_pos::{MultiSpan, Span};
/// Used for emitting structured error messages and other diagnostic information.
+///
+/// If there is some state in a downstream crate you would like to
+/// access in the methods of `DiagnosticBuilder` here, consider
+/// extending `HandlerFlags`, accessed via `self.handler.flags`.
#[must_use]
#[derive(Clone)]
pub struct DiagnosticBuilder<'a> {
/// it easy to declare such methods on the builder.
macro_rules! forward {
// Forward pattern for &self -> &Self
- (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
+ (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
pub fn $n(&self, $($name: $ty),*) -> &Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
};
// Forward pattern for &mut self -> &mut Self
- (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+ (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
// Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
// type parameter. No obvious way to make this more generic.
- (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+ (pub fn $n:ident<S: Into<MultiSpan>>(
+ &mut self,
+ $($name:ident: $ty:ty),*
+ $(,)*) -> &mut Self) => {
pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
self.cancel();
}
- /// Buffers the diagnostic for later emission.
- pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
+ /// Buffers the diagnostic for later emission, unless handler
+ /// has disabled such buffering.
+ pub fn buffer(mut self, buffered_diagnostics: &mut Vec<Diagnostic>) {
+ if self.handler.flags.dont_buffer_diagnostics || self.handler.flags.treat_err_as_bug {
+ self.emit();
+ return;
+ }
+
// We need to use `ptr::read` because `DiagnosticBuilder`
// implements `Drop`.
let diagnostic;
diagnostic = ::std::ptr::read(&self.diagnostic);
::std::mem::forget(self);
};
+ // Logging here is useful to help track down where in logs an error was
+ // actually emitted.
+ debug!("buffer: diagnostic={:?}", diagnostic);
buffered_diagnostics.push(diagnostic);
}
forward!(pub fn note_expected_found(&mut self,
label: &dyn fmt::Display,
expected: DiagnosticStyledString,
- found: DiagnosticStyledString)
- -> &mut Self);
+ found: DiagnosticStyledString,
+ ) -> &mut Self);
forward!(pub fn note_expected_found_extra(&mut self,
label: &dyn fmt::Display,
expected: DiagnosticStyledString,
found: DiagnosticStyledString,
expected_extra: &dyn fmt::Display,
- found_extra: &dyn fmt::Display)
- -> &mut Self);
+ found_extra: &dyn fmt::Display,
+ ) -> &mut Self);
forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
sp: S,
- msg: &str)
- -> &mut Self);
+ msg: &str,
+ ) -> &mut Self);
forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
sp: S,
- msg: &str)
- -> &mut Self);
- forward!(pub fn span_suggestion_short(&mut self,
- sp: Span,
- msg: &str,
- suggestion: String)
- -> &mut Self);
+ msg: &str,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+ forward!(pub fn span_suggestion_short(
+ &mut self,
+ sp: Span,
+ msg: &str,
+ suggestion: String,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
forward!(pub fn multipart_suggestion(
&mut self,
msg: &str,
- suggestion: Vec<(Span, String)>
+ suggestion: Vec<(Span, String)>,
) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestion_with_applicability`")]
forward!(pub fn span_suggestion(&mut self,
sp: Span,
msg: &str,
- suggestion: String)
- -> &mut Self);
+ suggestion: String,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestions_with_applicability`")]
forward!(pub fn span_suggestions(&mut self,
sp: Span,
msg: &str,
- suggestions: Vec<String>)
- -> &mut Self);
+ suggestions: Vec<String>,
+ ) -> &mut Self);
+
+ pub fn multipart_suggestion_with_applicability(&mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ if !self.allow_suggestions {
+ return self
+ }
+ self.diagnostic.multipart_suggestion_with_applicability(
+ msg,
+ suggestion,
+ applicability,
+ );
+ self
+ }
+
pub fn span_suggestion_with_applicability(&mut self,
sp: Span,
msg: &str,
ambiguity_errors: Vec<AmbiguityError<'a>>,
/// `use` injections are delayed for better placement and deduplication
use_injections: Vec<UseError<'a>>,
- /// `use` injections for proc macros wrongly imported with #[macro_use]
- proc_mac_errors: Vec<macros::ProcMacError>,
/// crate-local macro expanded `macro_export` referred to by a module-relative path
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,
- /// A set of procedural macros imported by `#[macro_use]` that have already been warned about
- warned_proc_macros: FxHashSet<Name>,
-
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
/// This table maps struct IDs into struct constructor IDs,
privacy_errors: Vec::new(),
ambiguity_errors: Vec::new(),
use_injections: Vec::new(),
- proc_mac_errors: Vec::new(),
macro_expanded_macro_export_errors: BTreeSet::new(),
arenas,
local_macro_def_scopes: FxHashMap(),
name_already_seen: FxHashMap(),
whitelisted_legacy_custom_derives: Vec::new(),
- warned_proc_macros: FxHashSet(),
potentially_unused_imports: Vec::new(),
struct_constructors: DefIdMap(),
found_unresolved_macro: false,
err.span_label(base_span,
"expecting a type here because of type ascription");
if line_sp != line_base_sp {
- err.span_suggestion_short(sp,
- "did you mean to use `;` here instead?",
- ";".to_string());
+ err.span_suggestion_short_with_applicability(
+ sp,
+ "did you mean to use `;` here instead?",
+ ";".to_string(),
+ Applicability::MaybeIncorrect,
+ );
}
break;
} else if snippet.trim().len() != 0 {
fn report_errors(&mut self, krate: &Crate) {
self.report_with_use_injections(krate);
- self.report_proc_macro_import(krate);
let mut reported_spans = FxHashSet();
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
*candidate = format!("use {};\n{}", candidate, additional_newline);
}
- err.span_suggestions(span, &msg, path_strings);
+ err.span_suggestions_with_applicability(
+ span,
+ &msg,
+ path_strings,
+ Applicability::Unspecified,
+ );
} else {
let mut msg = msg;
msg.push(':');
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
let suggestions = compatible_variants.iter()
.map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
- err.span_suggestions(expr.span,
- "try using a variant of the expected type",
- suggestions);
+ err.span_suggestions_with_applicability(
+ expr.span,
+ "try using a variant of the expected type",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
}
}
src,
if needs_paren { ")" } else { "" },
expected_ty);
- let into_suggestion = format!("{}{}{}.into()",
- if needs_paren { "(" } else { "" },
- src,
- if needs_paren { ")" } else { "" });
+ let into_suggestion = format!(
+ "{}{}{}.into()",
+ if needs_paren { "(" } else { "" },
+ src,
+ if needs_paren { ")" } else { "" },
+ );
+ let literal_is_ty_suffixed = |expr: &hir::Expr| {
+ if let hir::ExprKind::Lit(lit) = &expr.node {
+ lit.node.is_suffixed()
+ } else {
+ false
+ }
+ };
+
+ let into_sugg = into_suggestion.clone();
+ let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder,
+ note: Option<&str>| {
+ let suggest_msg = if literal_is_ty_suffixed(expr) {
+ format!(
+ "change the type of the numeric literal from `{}` to `{}`",
+ checked_ty,
+ expected_ty,
+ )
+ } else {
+ match note {
+ Some(note) => format!("{}, which {}", msg, note),
+ _ => format!("{} in a lossless way", msg),
+ }
+ };
+
+ let suffix_suggestion = format!(
+ "{}{}{}{}",
+ if needs_paren { "(" } else { "" },
+ src.trim_right_matches(&checked_ty.to_string()),
+ expected_ty,
+ if needs_paren { ")" } else { "" },
+ );
+
+ err.span_suggestion_with_applicability(
+ expr.span,
+ &suggest_msg,
+ if literal_is_ty_suffixed(expr) {
+ suffix_suggestion
+ } else {
+ into_sugg
+ },
+ Applicability::MachineApplicable,
+ );
+ };
match (&expected_ty.sty, &checked_ty.sty) {
(&ty::Int(ref exp), &ty::Int(ref found)) => {
}
}
_ => {
- err.span_suggestion_with_applicability(
- expr.span,
- &format!("{}, which {}", msg, will_sign_extend),
- into_suggestion,
- Applicability::MachineApplicable
+ suggest_to_change_suffix_or_into(
+ err,
+ Some(will_sign_extend),
);
}
}
}
}
_ => {
- err.span_suggestion_with_applicability(
- expr.span,
- &format!("{}, which {}", msg, will_zero_extend),
- into_suggestion,
- Applicability::MachineApplicable
- );
+ suggest_to_change_suffix_or_into(
+ err,
+ Some(will_zero_extend),
+ );
}
}
true
}
(&ty::Float(ref exp), &ty::Float(ref found)) => {
if found.bit_width() < exp.bit_width() {
- err.span_suggestion_with_applicability(
- expr.span,
- &format!("{} in a lossless way", msg),
- into_suggestion,
- Applicability::MachineApplicable
- );
+ suggest_to_change_suffix_or_into(
+ err,
+ None,
+ );
} else if can_cast {
err.span_suggestion_with_applicability(
expr.span,
let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
let implicit_region_bound = body_id.map(|body_id| {
let body = tcx.hir.body(body_id);
- tcx.mk_region(ty::ReScope(region::Scope::CallSite(body.value.hir_id.local_id)))
+ tcx.mk_region(ty::ReScope(region::Scope {
+ id: body.value.hir_id.local_id,
+ data: region::ScopeData::CallSite
+ }))
});
Inherited {
let base = self.tcx.hir.node_to_pretty_string(base.id);
let msg = format!("`{}` is a native pointer; try dereferencing it", base);
let suggestion = format!("(*{}).{}", base, field);
- err.span_suggestion(field.span, &msg, suggestion);
+ err.span_suggestion_with_applicability(
+ field.span,
+ &msg,
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
}
_ => {}
}
found: Ty<'tcx>,
) {
if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) {
- err.span_suggestion(sp, msg, suggestion);
+ err.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::MachineApplicable,
+ );
} else if !self.check_for_cast(err, expr, found, expected) {
let methods = self.get_conversion_methods(expr.span, expected, found);
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
}
}) .collect::<Vec<_>>();
if !suggestions.is_empty() {
- err.span_suggestions(expr.span, "try using a conversion method", suggestions);
+ err.span_suggestions_with_applicability(
+ expr.span,
+ "try using a conversion method",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
}
}
}