Skip to content

Commit 47575bb

Browse files
committed
Auto merge of #98816 - estebank:implicit-sized, r=oli-obk
Track implicit `Sized` obligations in type params When we evaluate `ty::GenericPredicates` we introduce the implicit `Sized` predicate of type params, but we do so with only the `Predicate` its `Span` as context, we don't have an `Obligation` or `ObligationCauseCode` we could influence. To try and carry this information through, we add a new field to `ty::GenericPredicates` that tracks both which predicates come from a type param and whether that param has any bounds already (to use in suggestions). We also suggest adding a `?Sized` bound if appropriate on E0599. Address part of #98539.
2 parents 06754d8 + 385c793 commit 47575bb

File tree

66 files changed

+283
-125
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+283
-125
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/wf.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
270270
}
271271

272272
fn normalize(mut self) -> Vec<traits::PredicateObligation<'tcx>> {
273-
let cause = self.cause(traits::MiscObligation);
273+
let cause = self.cause(traits::WellFormed(None));
274274
let infcx = &mut self.infcx;
275275
let param_env = self.param_env;
276276
let mut obligations = Vec::with_capacity(self.out.len());
@@ -384,7 +384,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
384384
self.out.extend(obligations);
385385

386386
let tcx = self.tcx();
387-
let cause = self.cause(traits::MiscObligation);
387+
let cause = self.cause(traits::WellFormed(None));
388388
let param_env = self.param_env;
389389
let depth = self.recursion_depth;
390390

@@ -444,7 +444,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
444444
let predicate =
445445
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
446446
.to_predicate(self.tcx());
447-
let cause = self.cause(traits::MiscObligation);
447+
let cause = self.cause(traits::WellFormed(None));
448448
self.out.push(traits::Obligation::with_depth(
449449
cause,
450450
self.recursion_depth,
@@ -456,7 +456,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
456456
let resolved = self.infcx.shallow_resolve(infer);
457457
// the `InferConst` changed, meaning that we made progress.
458458
if resolved != infer {
459-
let cause = self.cause(traits::MiscObligation);
459+
let cause = self.cause(traits::WellFormed(None));
460460

461461
let resolved_constant = self.infcx.tcx.mk_const(ty::ConstS {
462462
kind: ty::ConstKind::Infer(resolved),
@@ -647,7 +647,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
647647
let defer_to_coercion = self.tcx().features().object_safe_for_dispatch;
648648

649649
if !defer_to_coercion {
650-
let cause = self.cause(traits::MiscObligation);
650+
let cause = self.cause(traits::WellFormed(None));
651651
let component_traits = data.auto_traits().chain(data.principal_def_id());
652652
let tcx = self.tcx();
653653
self.out.extend(component_traits.map(|did| {
@@ -678,7 +678,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
678678
let ty = self.infcx.shallow_resolve(ty);
679679
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
680680
// Not yet resolved, but we've made progress.
681-
let cause = self.cause(traits::MiscObligation);
681+
let cause = self.cause(traits::WellFormed(None));
682682
self.out.push(traits::Obligation::with_depth(
683683
cause,
684684
self.recursion_depth,

Diff for: compiler/rustc_typeck/src/check/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
117117
};
118118

119119
// we must check that return type of called functions is WF:
120-
self.register_wf_obligation(output.into(), call_expr.span, traits::MiscObligation);
120+
self.register_wf_obligation(output.into(), call_expr.span, traits::WellFormed(None));
121121

122122
output
123123
}

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
496496

497497
pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
498498
let t = <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_t);
499-
self.register_wf_obligation(t.into(), ast_t.span, traits::MiscObligation);
499+
self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
500500
t
501501
}
502502

@@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
526526
self.register_wf_obligation(
527527
c.into(),
528528
self.tcx.hir().span(ast_c.hir_id),
529-
ObligationCauseCode::MiscObligation,
529+
ObligationCauseCode::WellFormed(None),
530530
);
531531
c
532532
}
@@ -544,7 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
544544
self.register_wf_obligation(
545545
c.into(),
546546
self.tcx.hir().span(ast_c.hir_id),
547-
ObligationCauseCode::MiscObligation,
547+
ObligationCauseCode::WellFormed(None),
548548
);
549549
c
550550
}
@@ -607,7 +607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
607607
for arg in substs.iter().filter(|arg| {
608608
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
609609
}) {
610-
self.register_wf_obligation(arg, expr.span, traits::MiscObligation);
610+
self.register_wf_obligation(arg, expr.span, traits::WellFormed(None));
611611
}
612612
}
613613

Diff for: compiler/rustc_typeck/src/check/method/confirm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
501501
// the function type must also be well-formed (this is not
502502
// implied by the substs being well-formed because of inherent
503503
// impls and late-bound regions - see issue #28609).
504-
self.register_wf_obligation(fty.into(), self.span, traits::MiscObligation);
504+
self.register_wf_obligation(fty.into(), self.span, traits::WellFormed(None));
505505
}
506506

507507
///////////////////////////////////////////////////////////////////////////

Diff for: compiler/rustc_typeck/src/check/method/suggest.rs

+39-12
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
348348
let type_param = generics.type_param(param_type, self.tcx);
349349
Some(self.tcx.def_span(type_param.def_id))
350350
}
351-
ty::Adt(def, _) if def.did().is_local() => {
352-
tcx.def_ident_span(def.did()).map(|span| span)
353-
}
351+
ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
354352
_ => None,
355353
};
356354

@@ -621,12 +619,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
621619
// Find all the requirements that come from a local `impl` block.
622620
let mut skip_list: FxHashSet<_> = Default::default();
623621
let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
624-
for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates
622+
for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
625623
.iter()
626624
.filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
627625
.filter_map(|(p, parent, c)| match c.code() {
628626
ObligationCauseCode::ImplDerivedObligation(ref data) => {
629-
Some((&data.derived, p, parent, data.impl_def_id, data.span))
627+
Some((&data.derived, p, parent, data.impl_def_id, data))
630628
}
631629
_ => None,
632630
})
@@ -695,9 +693,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
695693
let _ = format_pred(*pred);
696694
}
697695
skip_list.insert(p);
698-
let mut spans = if cause_span != *item_span {
699-
let mut spans: MultiSpan = cause_span.into();
700-
spans.push_span_label(cause_span, unsatisfied_msg);
696+
let mut spans = if cause.span != *item_span {
697+
let mut spans: MultiSpan = cause.span.into();
698+
spans.push_span_label(cause.span, unsatisfied_msg);
701699
spans
702700
} else {
703701
ident.span.into()
@@ -709,7 +707,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
709707

710708
// Unmet obligation coming from an `impl`.
711709
Some(Node::Item(hir::Item {
712-
kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
710+
kind:
711+
hir::ItemKind::Impl(hir::Impl {
712+
of_trait, self_ty, generics, ..
713+
}),
713714
span: item_span,
714715
..
715716
})) if !matches!(
@@ -725,14 +726,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
725726
Some(ExpnKind::Macro(MacroKind::Derive, _))
726727
) =>
727728
{
729+
let sized_pred =
730+
unsatisfied_predicates.iter().any(|(pred, _, _)| {
731+
match pred.kind().skip_binder() {
732+
ty::PredicateKind::Trait(pred) => {
733+
Some(pred.def_id())
734+
== self.tcx.lang_items().sized_trait()
735+
&& pred.polarity == ty::ImplPolarity::Positive
736+
}
737+
_ => false,
738+
}
739+
});
740+
for param in generics.params {
741+
if param.span == cause.span && sized_pred {
742+
let (sp, sugg) = match param.colon_span {
743+
Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
744+
None => (param.span.shrink_to_hi(), ": ?Sized"),
745+
};
746+
err.span_suggestion_verbose(
747+
sp,
748+
"consider relaxing the type parameter's implicit \
749+
`Sized` bound",
750+
sugg,
751+
Applicability::MachineApplicable,
752+
);
753+
}
754+
}
728755
if let Some(pred) = parent_p {
729756
// Done to add the "doesn't satisfy" `span_label`.
730757
let _ = format_pred(*pred);
731758
}
732759
skip_list.insert(p);
733-
let mut spans = if cause_span != *item_span {
734-
let mut spans: MultiSpan = cause_span.into();
735-
spans.push_span_label(cause_span, unsatisfied_msg);
760+
let mut spans = if cause.span != *item_span {
761+
let mut spans: MultiSpan = cause.span.into();
762+
spans.push_span_label(cause.span, unsatisfied_msg);
736763
spans
737764
} else {
738765
let mut spans = Vec::with_capacity(2);

Diff for: compiler/rustc_typeck/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
11801180
fcx.register_bound(
11811181
item_ty,
11821182
tcx.require_lang_item(LangItem::Sized, None),
1183-
traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
1183+
traits::ObligationCause::new(ty_span, fcx.body_id, traits::WellFormed(None)),
11841184
);
11851185
}
11861186

Diff for: compiler/rustc_typeck/src/hir_wf_check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn diagnostic_hir_wf_check<'tcx>(
7272
let cause = traits::ObligationCause::new(
7373
ty.span,
7474
self.hir_id,
75-
traits::ObligationCauseCode::MiscObligation,
75+
traits::ObligationCauseCode::WellFormed(None),
7676
);
7777
fulfill.register_predicate_obligation(
7878
&infcx,

Diff for: src/test/ui/associated-item/associated-item-enum.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `mispellable` found for enum `
22
--> $DIR/associated-item-enum.rs:17:11
33
|
44
LL | enum Enum { Variant }
5-
| ---- variant or associated item `mispellable` not found for this enum
5+
| --------- variant or associated item `mispellable` not found for this enum
66
...
77
LL | Enum::mispellable();
88
| ^^^^^^^^^^^
@@ -14,7 +14,7 @@ error[E0599]: no variant or associated item named `mispellable_trait` found for
1414
--> $DIR/associated-item-enum.rs:18:11
1515
|
1616
LL | enum Enum { Variant }
17-
| ---- variant or associated item `mispellable_trait` not found for this enum
17+
| --------- variant or associated item `mispellable_trait` not found for this enum
1818
...
1919
LL | Enum::mispellable_trait();
2020
| ^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `
2626
--> $DIR/associated-item-enum.rs:19:11
2727
|
2828
LL | enum Enum { Variant }
29-
| ---- variant or associated item `MISPELLABLE` not found for this enum
29+
| --------- variant or associated item `MISPELLABLE` not found for this enum
3030
...
3131
LL | Enum::MISPELLABLE;
3232
| ^^^^^^^^^^^

Diff for: src/test/ui/async-await/pin-needed-to-poll.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `poll` found for struct `Sleep` in the current sco
22
--> $DIR/pin-needed-to-poll.rs:42:20
33
|
44
LL | struct Sleep;
5-
| ----- method `poll` not found for this struct
5+
| ------------ method `poll` not found for this struct
66
...
77
LL | self.sleep.poll(cx)
88
| ^^^^ method not found in `Sleep`

Diff for: src/test/ui/bogus-tag.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Hsl` found for enum `Color` i
22
--> $DIR/bogus-tag.rs:7:16
33
|
44
LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
5-
| ----- variant or associated item `Hsl` not found for this enum
5+
| ---------- variant or associated item `Hsl` not found for this enum
66
...
77
LL | Color::Hsl(h, s, l) => { println!("hsl"); }
88
| ^^^ variant or associated item not found in `Color`

Diff for: src/test/ui/confuse-field-and-method/issue-18343.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
22
--> $DIR/issue-18343.rs:7:7
33
|
44
LL | struct Obj<F> where F: FnMut() -> u32 {
5-
| --- method `closure` not found for this struct
5+
| ------------- method `closure` not found for this struct
66
...
77
LL | o.closure();
88
| ^^^^^^^ field, not a method

Diff for: src/test/ui/confuse-field-and-method/issue-2392.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
22
--> $DIR/issue-2392.rs:36:15
33
|
44
LL | struct Obj<F> where F: FnOnce() -> u32 {
5-
| --- method `closure` not found for this struct
5+
| ------------- method `closure` not found for this struct
66
...
77
LL | o_closure.closure();
88
| ^^^^^^^ field, not a method
@@ -16,7 +16,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren
1616
--> $DIR/issue-2392.rs:38:15
1717
|
1818
LL | struct Obj<F> where F: FnOnce() -> u32 {
19-
| --- method `not_closure` not found for this struct
19+
| ------------- method `not_closure` not found for this struct
2020
...
2121
LL | o_closure.not_closure();
2222
| ^^^^^^^^^^^-- help: remove the arguments
@@ -27,7 +27,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
2727
--> $DIR/issue-2392.rs:42:12
2828
|
2929
LL | struct Obj<F> where F: FnOnce() -> u32 {
30-
| --- method `closure` not found for this struct
30+
| ------------- method `closure` not found for this struct
3131
...
3232
LL | o_func.closure();
3333
| ^^^^^^^ field, not a method
@@ -41,7 +41,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the
4141
--> $DIR/issue-2392.rs:45:14
4242
|
4343
LL | struct BoxedObj {
44-
| -------- method `boxed_closure` not found for this struct
44+
| --------------- method `boxed_closure` not found for this struct
4545
...
4646
LL | boxed_fn.boxed_closure();
4747
| ^^^^^^^^^^^^^ field, not a method
@@ -55,7 +55,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the
5555
--> $DIR/issue-2392.rs:48:19
5656
|
5757
LL | struct BoxedObj {
58-
| -------- method `boxed_closure` not found for this struct
58+
| --------------- method `boxed_closure` not found for this struct
5959
...
6060
LL | boxed_closure.boxed_closure();
6161
| ^^^^^^^^^^^^^ field, not a method
@@ -69,7 +69,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
6969
--> $DIR/issue-2392.rs:53:12
7070
|
7171
LL | struct Obj<F> where F: FnOnce() -> u32 {
72-
| --- method `closure` not found for this struct
72+
| ------------- method `closure` not found for this struct
7373
...
7474
LL | w.wrap.closure();
7575
| ^^^^^^^ field, not a method
@@ -83,7 +83,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren
8383
--> $DIR/issue-2392.rs:55:12
8484
|
8585
LL | struct Obj<F> where F: FnOnce() -> u32 {
86-
| --- method `not_closure` not found for this struct
86+
| ------------- method `not_closure` not found for this struct
8787
...
8888
LL | w.wrap.not_closure();
8989
| ^^^^^^^^^^^-- help: remove the arguments
@@ -94,7 +94,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
9494
--> $DIR/issue-2392.rs:58:24
9595
|
9696
LL | struct Obj<F> where F: FnOnce() -> u32 {
97-
| --- method `closure` not found for this struct
97+
| ------------- method `closure` not found for this struct
9898
...
9999
LL | check_expression().closure();
100100
| ^^^^^^^ field, not a method
@@ -108,7 +108,7 @@ error[E0599]: no method named `f1` found for struct `FuncContainer` in the curre
108108
--> $DIR/issue-2392.rs:64:31
109109
|
110110
LL | struct FuncContainer {
111-
| ------------- method `f1` not found for this struct
111+
| -------------------- method `f1` not found for this struct
112112
...
113113
LL | (*self.container).f1(1);
114114
| ^^ field, not a method
@@ -122,7 +122,7 @@ error[E0599]: no method named `f2` found for struct `FuncContainer` in the curre
122122
--> $DIR/issue-2392.rs:65:31
123123
|
124124
LL | struct FuncContainer {
125-
| ------------- method `f2` not found for this struct
125+
| -------------------- method `f2` not found for this struct
126126
...
127127
LL | (*self.container).f2(1);
128128
| ^^ field, not a method
@@ -136,7 +136,7 @@ error[E0599]: no method named `f3` found for struct `FuncContainer` in the curre
136136
--> $DIR/issue-2392.rs:66:31
137137
|
138138
LL | struct FuncContainer {
139-
| ------------- method `f3` not found for this struct
139+
| -------------------- method `f3` not found for this struct
140140
...
141141
LL | (*self.container).f3(1);
142142
| ^^ field, not a method

Diff for: src/test/ui/confuse-field-and-method/issue-32128.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `example` found for struct `Example` in the curren
22
--> $DIR/issue-32128.rs:12:10
33
|
44
LL | struct Example {
5-
| ------- method `example` not found for this struct
5+
| -------------- method `example` not found for this struct
66
...
77
LL | demo.example(1);
88
| ^^^^^^^ field, not a method

Diff for: src/test/ui/confuse-field-and-method/private-field.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `dog_age` found for struct `Dog` in the current sc
22
--> $DIR/private-field.rs:16:23
33
|
44
LL | pub struct Dog {
5-
| --- method `dog_age` not found for this struct
5+
| -------------- method `dog_age` not found for this struct
66
...
77
LL | let dog_age = dog.dog_age();
88
| ^^^^^^^ private field, not a method

0 commit comments

Comments
 (0)