diff options
Diffstat (limited to 'compiler')
8 files changed, 117 insertions, 19 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c3f2213229a..1e3f9f7464d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1430,6 +1430,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and + /// the return type of `async fn`s. + /// + /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`. + /// + /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using + /// the message in `secondary_span` as the primary label, and apply the message that would + /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on + /// E0271, like `src/test/ui/issues/issue-39970.stderr`. pub fn note_type_err( &self, diag: &mut DiagnosticBuilder<'tcx>, @@ -1437,6 +1446,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { secondary_span: Option<(Span, String)>, mut values: Option<ValuePairs<'tcx>>, terr: &TypeError<'tcx>, + swap_secondary_and_primary: bool, ) { let span = cause.span(self.tcx); debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr); @@ -1613,9 +1623,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match terr { TypeError::ObjectUnsafeCoercion(_) => {} _ => { - diag.span_label(span, terr.to_string()); + let mut label_or_note = |span: Span, msg: &str| { + if &[span] == diag.span.primary_spans() { + diag.span_label(span, msg); + } else { + diag.span_note(span, msg); + } + }; if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, msg); + if swap_secondary_and_primary { + let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound { + expected, + .. + })) = values + { + format!("expected this to be `{}`", expected) + } else { + terr.to_string() + }; + label_or_note(sp, &terr); + label_or_note(span, &msg); + } else { + label_or_note(span, &terr.to_string()); + label_or_note(sp, &msg); + } + } else { + label_or_note(span, &terr.to_string()); } } }; @@ -2049,7 +2082,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str) } }; - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); diag } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index bda40a9abb0..1b4566fd026 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -118,8 +118,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"), TupleSize(values) => write!( f, - "expected a tuple with {} element{}, \ - found one with {} element{}", + "expected a tuple with {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, @@ -127,8 +126,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ), FixedArraySize(values) => write!( f, - "expected an array with a fixed size of {} element{}, \ - found one with {} element{}", + "expected an array with a fixed size of {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index d9f86fbc23b..645295d4839 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1338,7 +1338,46 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { "type mismatch resolving `{}`", predicate ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); + let secondary_span = match predicate.kind().skip_binder() { + ty::PredicateKind::Projection(proj) => self + .tcx + .opt_associated_item(proj.projection_ty.item_def_id) + .and_then(|trait_assoc_item| { + self.tcx + .trait_of_item(proj.projection_ty.item_def_id) + .map(|id| (trait_assoc_item, id)) + }) + .and_then(|(trait_assoc_item, id)| { + self.tcx.find_map_relevant_impl( + id, + proj.projection_ty.self_ty(), + |did| { + self.tcx + .associated_items(did) + .in_definition_order() + .filter(|assoc| assoc.ident == trait_assoc_item.ident) + .next() + }, + ) + }) + .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(ty), + .. + }), + ) => { + Some((ty.span, format!("type mismatch resolving `{}`", predicate))) + } + _ => None, + }), + _ => None, + }; + self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true); self.note_obligation_cause(&mut diag, obligation); diag.emit(); } @@ -2095,10 +2134,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); - - if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + let self_ty = parent_trait_ref.skip_binder().self_ty(); + if obligated_types.iter().any(|ot| ot == &self_ty) { return true; } + if let ty::Adt(def, substs) = self_ty.kind() { + if let [arg] = &substs[..] { + if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() { + if let ty::Adt(inner_def, _) = ty.kind() { + if inner_def == def { + return true; + } + } + } + } + } } false } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d0b61b24308..db76ade296b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2186,6 +2186,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { seen_requirements, ) }); + } else { + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + err, + &parent_predicate, + &cause_code.peel_derives(), + obligated_types, + seen_requirements, + ) + }); } } ObligationCauseCode::ImplDerivedObligation(ref data) => { diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 511a2d7ddac..a397ee771af 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -638,7 +638,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty); self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty); - if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) { + debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); + + if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) + && !self.cast_ty.has_infer_types() + { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index a6b16e7f0d4..4e06608be5d 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -730,7 +730,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { let abi = sig.header.abi; fn_maybe_err(tcx, item.ident.span, abi); } - hir::TraitItemKind::Type(.., Some(_default)) => { + hir::TraitItemKind::Type(.., Some(default)) => { let assoc_item = tcx.associated_item(item.def_id); let trait_substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); @@ -738,7 +738,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { tcx, assoc_item, assoc_item, - item.span, + default.span, ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, ); } @@ -987,12 +987,12 @@ pub(super) fn check_impl_items_against_trait<'tcx>( opt_trait_span, ); } - hir::ImplItemKind::TyAlias(_) => { + hir::ImplItemKind::TyAlias(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); compare_ty_impl( tcx, &ty_impl_item, - impl_item.span, + impl_ty.span, &ty_trait_item, impl_trait_ref, opt_trait_span, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 44fc81a889d..6af0312f313 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -379,6 +379,7 @@ fn compare_predicate_entailment<'tcx>( found: impl_fty, })), &terr, + false, ); diag.emit(); return Err(ErrorReported); @@ -734,8 +735,7 @@ fn compare_number_of_method_arguments<'tcx>( tcx.sess, impl_span, E0050, - "method `{}` has {} but the declaration in \ - trait `{}` has {}", + "method `{}` has {} but the declaration in trait `{}` has {}", trait_m.ident, potentially_plural_count(impl_number_args, "parameter"), tcx.def_path_str(trait_m.def_id), @@ -1069,6 +1069,7 @@ crate fn compare_const_impl<'tcx>( found: impl_ty, })), &terr, + false, ); diag.emit(); } @@ -1099,7 +1100,8 @@ crate fn compare_ty_impl<'tcx>( let _: Result<(), ErrorReported> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; + let sp = tcx.def_span(impl_ty.def_id); + compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?; check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 1fc88829c77..17f07d0877e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -683,7 +683,8 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), - hir::ImplItemKind::TyAlias(ty) => (None, ty.span), + // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`. + hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span), _ => (None, impl_item.span), }; |
