about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-07-01 16:47:26 -0700
committerEsteban Küber <esteban@kuber.com.ar>2022-07-07 12:15:12 -0700
commitaf10a456c19c447ff2bff585537d52a8d532bd86 (patch)
treedfb4e9c247c42c7c495430f03b9bdda1013e749f /compiler
parentd5642acfe689ca704b8572ea8ca88e43aeb70a11 (diff)
downloadrust-af10a456c19c447ff2bff585537d52a8d532bd86.tar.gz
rust-af10a456c19c447ff2bff585537d52a8d532bd86.zip
Track implicit `Sized` obligations in type params
Suggest adding a `?Sized` bound if appropriate on E0599 by inspecting
the HIR Generics. (Fix #98539)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs51
1 files changed, 39 insertions, 12 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 4e1a105fc71..7bf167426f7 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -348,9 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let type_param = generics.type_param(param_type, self.tcx);
                         Some(self.tcx.def_span(type_param.def_id))
                     }
-                    ty::Adt(def, _) if def.did().is_local() => {
-                        tcx.def_ident_span(def.did()).map(|span| span)
-                    }
+                    ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
                     _ => None,
                 };
 
@@ -621,12 +619,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // Find all the requirements that come from a local `impl` block.
                     let mut skip_list: FxHashSet<_> = Default::default();
                     let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
-                    for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates
+                    for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
                         .iter()
                         .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
                         .filter_map(|(p, parent, c)| match c.code() {
                             ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                                Some((&data.derived, p, parent, data.impl_def_id, data.span))
+                                Some((&data.derived, p, parent, data.impl_def_id, data))
                             }
                             _ => None,
                         })
@@ -695,9 +693,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     let _ = format_pred(*pred);
                                 }
                                 skip_list.insert(p);
-                                let mut spans = if cause_span != *item_span {
-                                    let mut spans: MultiSpan = cause_span.into();
-                                    spans.push_span_label(cause_span, unsatisfied_msg);
+                                let mut spans = if cause.span != *item_span {
+                                    let mut spans: MultiSpan = cause.span.into();
+                                    spans.push_span_label(cause.span, unsatisfied_msg);
                                     spans
                                 } else {
                                     ident.span.into()
@@ -709,7 +707,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                             // Unmet obligation coming from an `impl`.
                             Some(Node::Item(hir::Item {
-                                kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                                kind:
+                                    hir::ItemKind::Impl(hir::Impl {
+                                        of_trait, self_ty, generics, ..
+                                    }),
                                 span: item_span,
                                 ..
                             })) if !matches!(
@@ -725,14 +726,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Some(ExpnKind::Macro(MacroKind::Derive, _))
                             ) =>
                             {
+                                let sized_pred =
+                                    unsatisfied_predicates.iter().any(|(pred, _, _)| {
+                                        match pred.kind().skip_binder() {
+                                            ty::PredicateKind::Trait(pred) => {
+                                                Some(pred.def_id())
+                                                    == self.tcx.lang_items().sized_trait()
+                                                    && pred.polarity == ty::ImplPolarity::Positive
+                                            }
+                                            _ => false,
+                                        }
+                                    });
+                                for param in generics.params {
+                                    if param.span == cause.span && sized_pred {
+                                        let (sp, sugg) = match param.colon_span {
+                                            Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
+                                            None => (param.span.shrink_to_hi(), ": ?Sized"),
+                                        };
+                                        err.span_suggestion_verbose(
+                                            sp,
+                                            "consider relaxing the type parameter's implicit \
+                                             `Sized` bound",
+                                            sugg,
+                                            Applicability::MachineApplicable,
+                                        );
+                                    }
+                                }
                                 if let Some(pred) = parent_p {
                                     // Done to add the "doesn't satisfy" `span_label`.
                                     let _ = format_pred(*pred);
                                 }
                                 skip_list.insert(p);
-                                let mut spans = if cause_span != *item_span {
-                                    let mut spans: MultiSpan = cause_span.into();
-                                    spans.push_span_label(cause_span, unsatisfied_msg);
+                                let mut spans = if cause.span != *item_span {
+                                    let mut spans: MultiSpan = cause.span.into();
+                                    spans.push_span_label(cause.span, unsatisfied_msg);
                                     spans
                                 } else {
                                     let mut spans = Vec::with_capacity(2);