mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Refactoring
This commit is contained in:
parent
95dc7efad0
commit
aaa02b3ff9
@ -368,7 +368,7 @@ pub fn raw_emit_lint(sess: &Session,
|
||||
lvlsrc: LevelSource,
|
||||
span: Option<Span>,
|
||||
msg: &str) {
|
||||
raw_struct_lint(sess, lint, lvlsrc, span, msg).map(|mut e| e.emit());
|
||||
raw_struct_lint(sess, lint, lvlsrc, span, msg).emit();
|
||||
}
|
||||
|
||||
pub fn raw_struct_lint<'a>(sess: &'a Session,
|
||||
@ -376,10 +376,10 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
|
||||
lvlsrc: LevelSource,
|
||||
span: Option<Span>,
|
||||
msg: &str)
|
||||
-> Option<DiagnosticBuilder<'a>> {
|
||||
-> DiagnosticBuilder<'a> {
|
||||
let (mut level, source) = lvlsrc;
|
||||
if level == Allow {
|
||||
return None;
|
||||
return sess.diagnostic().struct_dummy();
|
||||
}
|
||||
|
||||
let name = lint.name_lower();
|
||||
@ -416,7 +416,8 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
|
||||
if let Some(span) = def {
|
||||
err.span_note(span, "lint level defined here");
|
||||
}
|
||||
Some(err)
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
pub trait LintContext: Sized {
|
||||
@ -456,9 +457,9 @@ pub trait LintContext: Sized {
|
||||
lint: &'static Lint,
|
||||
span: Option<Span>,
|
||||
msg: &str)
|
||||
-> Option<DiagnosticBuilder> {
|
||||
-> DiagnosticBuilder {
|
||||
let (level, src) = match self.level_src(lint) {
|
||||
None => return None,
|
||||
None => return self.sess().diagnostic().struct_dummy(),
|
||||
Some(pair) => pair,
|
||||
};
|
||||
|
||||
@ -474,17 +475,14 @@ pub trait LintContext: Sized {
|
||||
lint: &'static Lint,
|
||||
span: Span,
|
||||
msg: &str)
|
||||
-> Option<DiagnosticBuilder> {
|
||||
-> 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) {
|
||||
let mut err = match self.lookup(lint, Some(span), msg) {
|
||||
Some(e) => e,
|
||||
None => return
|
||||
};
|
||||
let mut err = self.lookup(lint, Some(span), msg);
|
||||
if self.current_level(lint) != Level::Allow {
|
||||
if note_span == span {
|
||||
err.fileline_note(note_span, note);
|
||||
@ -498,10 +496,7 @@ pub trait LintContext: Sized {
|
||||
/// 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 = match self.lookup(lint, Some(span), msg) {
|
||||
Some(e) => e,
|
||||
None => return
|
||||
};
|
||||
let mut err = self.lookup(lint, Some(span), msg);
|
||||
self.span_lint(lint, span, msg);
|
||||
if self.current_level(lint) != Level::Allow {
|
||||
err.span_help(span, help);
|
||||
|
@ -237,7 +237,7 @@ pub trait ErrorReporting<'tcx> {
|
||||
fn report_type_error(&self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
terr: &TypeError<'tcx>)
|
||||
-> Option<DiagnosticBuilder<'tcx>>;
|
||||
-> DiagnosticBuilder<'tcx>;
|
||||
|
||||
fn check_and_note_conflicting_crates(&self,
|
||||
err: &mut DiagnosticBuilder,
|
||||
@ -478,11 +478,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
fn report_type_error(&self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
terr: &TypeError<'tcx>)
|
||||
-> Option<DiagnosticBuilder<'tcx>> {
|
||||
-> DiagnosticBuilder<'tcx> {
|
||||
let expected_found_str = match self.values_str(&trace.values) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return None; /* derived error */
|
||||
return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
|
||||
}
|
||||
};
|
||||
|
||||
@ -507,7 +507,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
Some(err)
|
||||
err
|
||||
}
|
||||
|
||||
/// Adds a note if the types come from similarly named crates
|
||||
@ -560,11 +560,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
trace: TypeTrace<'tcx>,
|
||||
terr: &TypeError<'tcx>) {
|
||||
let span = trace.origin.span();
|
||||
let err = self.report_type_error(trace, terr);
|
||||
err.map(|mut err| {
|
||||
self.tcx.note_and_explain_type_err(&mut err, terr, span);
|
||||
err.emit();
|
||||
});
|
||||
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
|
||||
|
@ -1281,7 +1281,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
mk_msg: M,
|
||||
actual_ty: String,
|
||||
err: Option<&TypeError<'tcx>>)
|
||||
-> Option<DiagnosticBuilder<'tcx>>
|
||||
-> DiagnosticBuilder<'tcx>
|
||||
where M: FnOnce(Option<String>, String) -> String,
|
||||
{
|
||||
self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
|
||||
@ -1296,7 +1296,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
where M: FnOnce(Option<String>, String) -> String,
|
||||
{
|
||||
self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
|
||||
.map(|mut e| e.emit());
|
||||
.emit();
|
||||
}
|
||||
|
||||
pub fn type_error_struct_str_with_expected<M>(&self,
|
||||
@ -1305,7 +1305,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
expected_ty: Option<Ty<'tcx>>,
|
||||
actual_ty: String,
|
||||
err: Option<&TypeError<'tcx>>)
|
||||
-> Option<DiagnosticBuilder<'tcx>>
|
||||
-> DiagnosticBuilder<'tcx>
|
||||
where M: FnOnce(Option<String>, String) -> String,
|
||||
{
|
||||
debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
|
||||
@ -1324,9 +1324,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
if let Some(err) = err {
|
||||
self.tcx.note_and_explain_type_err(&mut db, err, sp);
|
||||
}
|
||||
Some(db)
|
||||
db
|
||||
} else {
|
||||
None
|
||||
self.tcx.sess.diagnostic().struct_dummy()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1337,7 +1337,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
err: Option<&TypeError<'tcx>>)
|
||||
where M: FnOnce(String) -> String,
|
||||
{
|
||||
self.type_error_struct(sp, mk_msg, actual_ty, err).map(|mut e| e.emit());
|
||||
self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
|
||||
}
|
||||
|
||||
pub fn type_error_struct<M>(&self,
|
||||
@ -1345,14 +1345,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
mk_msg: M,
|
||||
actual_ty: Ty<'tcx>,
|
||||
err: Option<&TypeError<'tcx>>)
|
||||
-> Option<DiagnosticBuilder<'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 None;
|
||||
return self.tcx.sess.diagnostic().struct_dummy();
|
||||
}
|
||||
|
||||
self.type_error_struct_str(sp,
|
||||
|
@ -60,7 +60,7 @@ struct ExpectErrorEmitter {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -754,18 +754,17 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
if !reached_exit_without_self_call && !self_call_spans.is_empty() {
|
||||
let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp,
|
||||
"function cannot return without recurring");
|
||||
let mut db = db.as_mut();
|
||||
|
||||
// FIXME #19668: these could be span_lint_note's instead of this manual guard.
|
||||
if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
|
||||
// offer some help to the programmer.
|
||||
for call in &self_call_spans {
|
||||
db = db.map(|db| db.span_note(*call, "recursive call site"));
|
||||
db.span_note(*call, "recursive call site");
|
||||
}
|
||||
db = db.map(|db| db.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.map(|db| db.emit());
|
||||
db.emit();
|
||||
}
|
||||
|
||||
// all done
|
||||
|
@ -144,9 +144,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
|
||||
if let Some(sp) = child[ns].span() {
|
||||
let note = format!("first definition of {} `{}` here", ns_str, name);
|
||||
err.as_mut().map(|mut e| e.span_note(sp, ¬e));
|
||||
err.span_note(sp, ¬e);
|
||||
}
|
||||
err.as_mut().map(|mut e| e.emit());
|
||||
err.emit();
|
||||
child
|
||||
}
|
||||
}
|
||||
@ -261,10 +261,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
mod_spans[0],
|
||||
ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
|
||||
for other_span in mod_spans.iter().skip(1) {
|
||||
e.as_mut().map(|mut e| e.span_note(*other_span,
|
||||
"another `self` import appears here"));
|
||||
e.span_note(*other_span, "another `self` import appears here");
|
||||
}
|
||||
e.as_mut().map(|mut e| e.emit());
|
||||
e.emit();
|
||||
}
|
||||
|
||||
for source_item in source_items {
|
||||
|
@ -216,18 +216,18 @@ pub enum UnresolvedNameContext {
|
||||
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).map(|mut e| e.emit());
|
||||
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>)
|
||||
-> Option<DiagnosticBuilder<'a>> {
|
||||
-> DiagnosticBuilder<'a> {
|
||||
if !resolver.emit_errors {
|
||||
return None;
|
||||
return resolver.session.diagnostic().struct_dummy();
|
||||
}
|
||||
|
||||
Some(match resolution_error {
|
||||
match resolution_error {
|
||||
ResolutionError::TypeParametersFromOuterFunction => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
@ -532,7 +532,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
||||
E0435,
|
||||
"attempt to use a non-constant value in a constant")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -2202,10 +2202,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
// If it's a typedef, give a note
|
||||
if let DefTy(..) = path_res.base_def {
|
||||
err.as_mut().map(|mut e| e.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.as_mut().map(|mut e| e.emit());
|
||||
err.emit();
|
||||
Err(())
|
||||
}
|
||||
} else {
|
||||
@ -3493,11 +3493,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
||||
path_name);
|
||||
if self.emit_errors {
|
||||
err.as_mut().map(|mut e| e.fileline_help(expr.span, &msg));
|
||||
err.fileline_help(expr.span, &msg);
|
||||
} else {
|
||||
err.as_mut().map(|mut e| e.span_help(expr.span, &msg));
|
||||
err.span_help(expr.span, &msg);
|
||||
}
|
||||
err.as_mut().map(|mut e| e.emit());
|
||||
err.emit();
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
} else {
|
||||
// Write the result into the def map.
|
||||
@ -3534,11 +3534,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
||||
path_name);
|
||||
if self.emit_errors {
|
||||
err.as_mut().map(|mut e| e.fileline_help(expr.span, &msg));
|
||||
err.fileline_help(expr.span, &msg);
|
||||
} else {
|
||||
err.as_mut().map(|mut e| e.span_help(expr.span, &msg));
|
||||
err.span_help(expr.span, &msg);
|
||||
}
|
||||
err.as_mut().map(|mut e| e.emit());
|
||||
err.emit();
|
||||
}
|
||||
_ => {
|
||||
// Keep reporting some errors even if they're ignored above.
|
||||
|
@ -2213,11 +2213,9 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span,
|
||||
&format!("enum variant is more than three times larger ({} bytes) \
|
||||
than the next largest (ignoring padding)",
|
||||
largest))
|
||||
.map(|mut e| {
|
||||
e.span_note(enum_def.variants[largest_index].span,
|
||||
.span_note(enum_def.variants[largest_index].span,
|
||||
"this variant is the largest")
|
||||
.emit();
|
||||
});
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,20 +232,19 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|
||||
let mut err = fcx.type_error_struct(call_expr.span, |actual| {
|
||||
format!("expected function, found `{}`", actual)
|
||||
}, callee_ty, None);
|
||||
let mut err = err.as_mut();
|
||||
|
||||
if let hir::ExprCall(ref expr, _) = call_expr.node {
|
||||
let tcx = fcx.tcx();
|
||||
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()) {
|
||||
err = err.map(|e| e.span_note(span, "defined here"));
|
||||
err.span_note(span, "defined here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err.map(|e| e.emit());
|
||||
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
|
||||
|
@ -132,17 +132,15 @@ impl<'tcx> CastCheck<'tcx> {
|
||||
actual,
|
||||
fcx.infcx().ty_to_string(self.cast_ty))
|
||||
}, self.expr_ty, None)
|
||||
.map(|mut err| {
|
||||
err.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!()
|
||||
}));
|
||||
err.emit();
|
||||
});
|
||||
.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 => {
|
||||
struct_span_err!(fcx.tcx().sess, self.span, E0054, "cannot cast as `bool`")
|
||||
@ -174,10 +172,8 @@ impl<'tcx> CastCheck<'tcx> {
|
||||
actual,
|
||||
fcx.infcx().ty_to_string(self.cast_ty))
|
||||
}, self.expr_ty, None)
|
||||
.map(|mut err| {
|
||||
err.fileline_note(self.span, "vtable kinds may not match");
|
||||
err.emit();
|
||||
});
|
||||
.fileline_note(self.span, "vtable kinds may not match")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,103 +69,101 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
rcvr_ty,
|
||||
None);
|
||||
|
||||
if let Some(ref mut err) = err {
|
||||
// If the item has the name of a field, give a help note
|
||||
if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
|
||||
if let Some(field) = def.struct_variant().find_field_named(item_name) {
|
||||
let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
|
||||
Ok(expr_string) => expr_string,
|
||||
_ => "s".into() // Default to a generic placeholder for the
|
||||
// expression when we can't generate a string
|
||||
// snippet
|
||||
};
|
||||
// If the item has the name of a field, give a help note
|
||||
if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
|
||||
if let Some(field) = def.struct_variant().find_field_named(item_name) {
|
||||
let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
|
||||
Ok(expr_string) => expr_string,
|
||||
_ => "s".into() // Default to a generic placeholder for the
|
||||
// expression when we can't generate a string
|
||||
// snippet
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! span_did_you_mean {
|
||||
() => {
|
||||
err.span_note(span, &format!("did you mean to write `{0}.{1}`?",
|
||||
expr_string, item_name));
|
||||
}
|
||||
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);
|
||||
// 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!();
|
||||
}
|
||||
// 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 poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||
let obligation = Obligation::misc(span,
|
||||
fcx.body_id,
|
||||
poly_trait_ref
|
||||
.to_predicate());
|
||||
let mut selcx = SelectionContext::new(infcx);
|
||||
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!();
|
||||
}
|
||||
// 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 poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||
let obligation = Obligation::misc(span,
|
||||
fcx.body_id,
|
||||
poly_trait_ref
|
||||
.to_predicate());
|
||||
let mut selcx = SelectionContext::new(infcx);
|
||||
|
||||
if selcx.evaluate_obligation(&obligation) {
|
||||
span_stored_function!();
|
||||
} else {
|
||||
span_did_you_mean!();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
span_did_you_mean!();
|
||||
}
|
||||
if selcx.evaluate_obligation(&obligation) {
|
||||
span_stored_function!();
|
||||
} else {
|
||||
span_did_you_mean!();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
span_did_you_mean!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !static_sources.is_empty() {
|
||||
err.fileline_note(
|
||||
span,
|
||||
"found defined static methods, maybe a `self` is missing?");
|
||||
|
||||
report_candidates(fcx, err, span, item_name, static_sources);
|
||||
}
|
||||
|
||||
if !unsatisfied_predicates.is_empty() {
|
||||
let bound_list = unsatisfied_predicates.iter()
|
||||
.map(|p| format!("`{} : {}`",
|
||||
p.self_ty(),
|
||||
p))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
err.fileline_note(
|
||||
span,
|
||||
&format!("the method `{}` exists but the \
|
||||
following trait bounds were not satisfied: {}",
|
||||
item_name,
|
||||
bound_list));
|
||||
}
|
||||
|
||||
suggest_traits_to_import(fcx, err, span, rcvr_ty, item_name,
|
||||
rcvr_expr, out_of_scope_traits);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
if !static_sources.is_empty() {
|
||||
err.fileline_note(
|
||||
span,
|
||||
"found defined static methods, maybe a `self` is missing?");
|
||||
|
||||
report_candidates(fcx, &mut err, span, item_name, static_sources);
|
||||
}
|
||||
|
||||
if !unsatisfied_predicates.is_empty() {
|
||||
let bound_list = unsatisfied_predicates.iter()
|
||||
.map(|p| format!("`{} : {}`",
|
||||
p.self_ty(),
|
||||
p))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
err.fileline_note(
|
||||
span,
|
||||
&format!("the method `{}` exists but the \
|
||||
following trait bounds were not satisfied: {}",
|
||||
item_name,
|
||||
bound_list));
|
||||
}
|
||||
|
||||
suggest_traits_to_import(fcx, &mut err, span, rcvr_ty, item_name,
|
||||
rcvr_expr, out_of_scope_traits);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
MethodError::Ambiguity(sources) => {
|
||||
|
@ -1051,16 +1051,16 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
if t_cast.is_trait() {
|
||||
match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
|
||||
Ok(s) => {
|
||||
err.as_mut().unwrap().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!(err.as_mut().unwrap(), t_span,
|
||||
span_help!(err, t_span,
|
||||
"did you mean `&{}{}`?", mtstr, tstr),
|
||||
}
|
||||
} else {
|
||||
span_help!(err.as_mut().unwrap(), span,
|
||||
span_help!(err, span,
|
||||
"consider using an implicit coercion to `&{}{}` instead",
|
||||
mtstr, tstr);
|
||||
}
|
||||
@ -1068,20 +1068,20 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
ty::TyBox(..) => {
|
||||
match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
|
||||
Ok(s) => {
|
||||
err.as_mut().unwrap().span_suggestion(t_span,
|
||||
err.span_suggestion(t_span,
|
||||
"try casting to a `Box` instead:",
|
||||
format!("Box<{}>", s));
|
||||
},
|
||||
Err(_) =>
|
||||
span_help!(err.as_mut().unwrap(), t_span, "did you mean `Box<{}>`?", tstr),
|
||||
span_help!(err, t_span, "did you mean `Box<{}>`?", tstr),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_help!(err.as_mut().unwrap(), e_span,
|
||||
span_help!(err, e_span,
|
||||
"consider using a box or reference as appropriate");
|
||||
}
|
||||
}
|
||||
err.map(|mut e| e.emit());
|
||||
err.emit();
|
||||
fcx.write_error(id);
|
||||
}
|
||||
|
||||
@ -1630,7 +1630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
mk_msg: M,
|
||||
actual_ty: Ty<'tcx>,
|
||||
err: Option<&TypeError<'tcx>>)
|
||||
-> Option<DiagnosticBuilder<'tcx>>
|
||||
-> DiagnosticBuilder<'tcx>
|
||||
where M: FnOnce(String) -> String,
|
||||
{
|
||||
self.infcx().type_error_struct(sp, mk_msg, actual_ty, err)
|
||||
@ -2966,13 +2966,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
`{}`", field.node, actual)
|
||||
},
|
||||
expr_t, None)
|
||||
.unwrap()
|
||||
.fileline_help(field.span,
|
||||
"maybe a `()` to call it is missing? \
|
||||
If not, try an anonymous function")
|
||||
.emit();
|
||||
} else {
|
||||
fcx.type_error_struct(
|
||||
let mut err = fcx.type_error_struct(
|
||||
expr.span,
|
||||
|actual| {
|
||||
format!("attempted access of field `{}` on \
|
||||
@ -2981,13 +2980,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
field.node,
|
||||
actual)
|
||||
},
|
||||
expr_t, None)
|
||||
.map(|mut e| {
|
||||
if let ty::TyStruct(def, _) = expr_t.sty {
|
||||
suggest_field_names(&mut e, def.struct_variant(), field, vec![]);
|
||||
}
|
||||
e.emit();
|
||||
});
|
||||
expr_t, None);
|
||||
if let ty::TyStruct(def, _) = expr_t.sty {
|
||||
suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fcx.write_error(expr.id);
|
||||
@ -3089,7 +3086,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
field: &hir::Field,
|
||||
skip_fields: &[hir::Field]) {
|
||||
fcx.type_error_struct(
|
||||
let mut err = fcx.type_error_struct(
|
||||
field.name.span,
|
||||
|actual| if let ty::TyEnum(..) = ty.sty {
|
||||
format!("struct variant `{}::{}` has no field named `{}`",
|
||||
@ -3099,13 +3096,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
actual, field.name.node)
|
||||
},
|
||||
ty,
|
||||
None)
|
||||
.map(|mut e| {
|
||||
// prevent all specified fields from being suggested
|
||||
let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
|
||||
suggest_field_names(&mut e, variant, &field.name, skip_fields.collect());
|
||||
e.emit();
|
||||
});
|
||||
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(&mut err, variant, &field.name, skip_fields.collect());
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
|
@ -107,7 +107,6 @@ pub struct DiagnosticBuilder<'a> {
|
||||
code: Option<String>,
|
||||
span: Option<Span>,
|
||||
children: Vec<SubDiagnostic>,
|
||||
cancelled: bool,
|
||||
}
|
||||
|
||||
// For example a note attached to an error.
|
||||
@ -121,12 +120,12 @@ struct SubDiagnostic {
|
||||
impl<'a> DiagnosticBuilder<'a> {
|
||||
// Emit the diagnostic.
|
||||
pub fn emit(&mut self) {
|
||||
if self.cancelled {
|
||||
if self.cancelled() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.cancel();
|
||||
self.emitter.borrow_mut().emit_struct(&self);
|
||||
self.cancel();
|
||||
|
||||
// if self.is_fatal() {
|
||||
// panic!(FatalError);
|
||||
@ -135,8 +134,15 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||
|
||||
// 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.cancelled = true;
|
||||
self.level = Level::Cancelled;
|
||||
}
|
||||
|
||||
pub fn cancelled(&self) -> bool {
|
||||
self.level == Level::Cancelled
|
||||
}
|
||||
|
||||
pub fn is_fatal(&self) -> bool {
|
||||
@ -204,21 +210,28 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||
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,
|
||||
code: Option<String>,
|
||||
span: Option<Span>) -> DiagnosticBuilder<'a> {
|
||||
message: &str) -> DiagnosticBuilder<'a> {
|
||||
DiagnosticBuilder {
|
||||
emitter: emitter,
|
||||
level: level,
|
||||
message: message.to_owned(),
|
||||
code: code,
|
||||
span: span,
|
||||
code: None,
|
||||
span: None,
|
||||
children: vec![],
|
||||
cancelled: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,7 +262,7 @@ impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
|
||||
// we emit a bug.
|
||||
impl<'a> Drop for DiagnosticBuilder<'a> {
|
||||
fn drop(&mut self) {
|
||||
if !self.cancelled {
|
||||
if !self.cancelled() {
|
||||
self.emitter.borrow_mut().emit(None, "Error constructed but not emitted", None, Bug);
|
||||
panic!();
|
||||
}
|
||||
@ -290,11 +303,16 @@ impl Handler {
|
||||
}
|
||||
}
|
||||
|
||||
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, None, Some(sp));
|
||||
-> DiagnosticBuilder<'a> {
|
||||
let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
|
||||
result.span(sp);
|
||||
if !self.can_emit_warnings {
|
||||
result.cancel();
|
||||
}
|
||||
@ -304,19 +322,17 @@ impl Handler {
|
||||
sp: Span,
|
||||
msg: &str,
|
||||
code: &str)
|
||||
-> DiagnosticBuilder<'a> {
|
||||
let mut result = DiagnosticBuilder::new(&self.emit,
|
||||
Level::Warning,
|
||||
msg,
|
||||
Some(code.to_owned()),
|
||||
Some(sp));
|
||||
-> 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, None, None);
|
||||
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();
|
||||
}
|
||||
@ -325,42 +341,58 @@ impl Handler {
|
||||
pub fn struct_span_err<'a>(&'a self,
|
||||
sp: Span,
|
||||
msg: &str)
|
||||
-> DiagnosticBuilder<'a> {
|
||||
-> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Error, msg, None, Some(sp))
|
||||
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> {
|
||||
// FIXME (and below) this is potentially inaccurate, since the DiagnosticBuilder
|
||||
// might be cancelled.
|
||||
-> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Error, msg, Some(code.to_owned()), Some(sp))
|
||||
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> {
|
||||
pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Error, msg, None, None)
|
||||
DiagnosticBuilder::new(&self.emit, Level::Error, msg)
|
||||
}
|
||||
pub fn struct_span_fatal<'a>(&'a self,
|
||||
sp: Span,
|
||||
msg: &str)
|
||||
-> DiagnosticBuilder<'a> {
|
||||
-> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, None, Some(sp))
|
||||
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> {
|
||||
-> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, Some(code.to_owned()), Some(sp))
|
||||
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> {
|
||||
pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
|
||||
self.bump_err_count();
|
||||
DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, None, None)
|
||||
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 {
|
||||
@ -514,6 +546,7 @@ pub enum Level {
|
||||
Warning,
|
||||
Note,
|
||||
Help,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
impl fmt::Display for Level {
|
||||
@ -526,6 +559,7 @@ impl fmt::Display for Level {
|
||||
Warning => "warning".fmt(f),
|
||||
Note => "note".fmt(f),
|
||||
Help => "help".fmt(f),
|
||||
Cancelled => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -537,6 +571,7 @@ impl Level {
|
||||
Warning => term::color::BRIGHT_YELLOW,
|
||||
Note => term::color::BRIGHT_GREEN,
|
||||
Help => term::color::BRIGHT_CYAN,
|
||||
Cancelled => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user