X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_infer%2Fsrc%2Finfer%2Ferror_reporting%2Fmod.rs;h=79704b6adf78e0e6b204d701d014664d2e7c513a;hb=3d92100955ccca02dea7d775c91a954958582c74;hp=28fd03b878b2b69b2da3ef46b59a09823f1ea5f3;hpb=52372f9c71d8ade4cb815524f179119656f0aa2e;p=rust.git diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 28fd03b878b..b5c2d14e8d1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -60,13 +60,14 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; +use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; use rustc_middle::dep_graph::DepContext; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, @@ -79,6 +80,7 @@ use std::{cmp, fmt, iter}; mod note; +mod note_and_explain; mod suggest; pub(crate) mod need_type_info; @@ -1344,8 +1346,8 @@ fn lifetime_display(lifetime: Region<'_>) -> String { } (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => { - let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1); - let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2); + let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1); + let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2); let mut values = self.cmp_fn_sig(&sig1, &sig2); let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1)); let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2)); @@ -1356,7 +1358,7 @@ fn lifetime_display(lifetime: Region<'_>) -> String { } (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => { - let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1); + let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1); let mut values = self.cmp_fn_sig(&sig1, sig2); values.0.push_highlighted(format!( " {{{}}}", @@ -1366,7 +1368,7 @@ fn lifetime_display(lifetime: Region<'_>) -> String { } (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => { - let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2); + let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2); let mut values = self.cmp_fn_sig(sig1, &sig2); values.1.push_normal(format!( " {{{}}}", @@ -1468,51 +1470,17 @@ fn add_labels_for_types( for (key, values) in types.iter() { let count = values.len(); let kind = key.descr(); - let mut returned_async_output_error = false; for &sp in values { - if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error { - if [sp] != err.span.primary_spans() { - let mut span: MultiSpan = sp.into(); - span.push_span_label( - sp, - format!( - "checked the `Output` of this `async fn`, {}{} {}{}", - if count > 1 { "one of the " } else { "" }, - target, - kind, - pluralize!(count), - ), - ); - err.span_note( - span, - "while checking the return type of the `async fn`", - ); - } else { - err.span_label( - sp, - format!( - "checked the `Output` of this `async fn`, {}{} {}{}", - if count > 1 { "one of the " } else { "" }, - target, - kind, - pluralize!(count), - ), - ); - err.note("while checking the return type of the `async fn`"); - } - returned_async_output_error = true; - } else { - err.span_label( - sp, - format!( - "{}{} {}{}", - if count == 1 { "the " } else { "one of the " }, - target, - kind, - pluralize!(count), - ), - ); - } + err.span_label( + sp, + format!( + "{}{} {}{}", + if count == 1 { "the " } else { "one of the " }, + target, + kind, + pluralize!(count), + ), + ); } } } @@ -1535,7 +1503,11 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { // | // = note: expected unit type `()` // found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]` - if !self.ignore_span.overlaps(span) { + // + // Also ignore opaque `Future`s that come from async fns. + if !self.ignore_span.overlaps(span) + && !span.is_desugaring(DesugaringKind::Async) + { self.types.entry(kind).or_default().insert(span); } } @@ -1611,16 +1583,31 @@ enum Mismatch<'a> { { format!("expected this to be `{}`", expected) } else { - terr.to_string() + terr.to_string(self.tcx).to_string() }; label_or_note(sp, &terr); label_or_note(span, &msg); } else { - label_or_note(span, &terr.to_string()); + label_or_note(span, &terr.to_string(self.tcx)); label_or_note(sp, &msg); } } else { - label_or_note(span, &terr.to_string()); + if let Some(values) = values + && let Some((e, f)) = values.ty() + && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr + { + let e = self.tcx.erase_regions(e); + let f = self.tcx.erase_regions(f); + let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); + let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); + if expected == found { + label_or_note(span, &terr.to_string(self.tcx)); + } else { + label_or_note(span, &format!("expected {expected}, found {found}")); + } + } else { + label_or_note(span, &terr.to_string(self.tcx)); + } } if let Some((expected, found, exp_p, found_p)) = expected_found { @@ -1841,19 +1828,25 @@ enum Similar<'tcx> { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag); self.suggest_await_on_expect_found(cause, span, &exp_found, diag); + self.suggest_function_pointers(cause, span, &exp_found, diag); } } - // In some (most?) cases cause.body_id points to actual body, but in some cases - // it's an actual definition. According to the comments (e.g. in - // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter - // is relied upon by some other code. This might (or might not) need cleanup. - let body_owner_def_id = - self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { - self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id }) - }); self.check_and_note_conflicting_crates(diag, terr); - self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id()); + + self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id()); + if let Some(exp_found) = exp_found + && let exp_found = TypeError::Sorts(exp_found) + && exp_found != terr + { + self.note_and_explain_type_err( + diag, + exp_found, + cause, + span, + cause.body_id.to_def_id(), + ); + } if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values && let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() @@ -2585,7 +2578,7 @@ pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool { /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. - pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + pub fn same_type_modulo_infer>(&self, a: T, b: T) -> bool { let (a, b) = self.resolve_vars_if_possible((a, b)); SameTypeModuloInfer(self).relate(a, b).is_ok() }