Skip to content

Commit

Permalink
Auto merge of #98816 - estebank:implicit-sized, r=oli-obk
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Jul 8, 2022
2 parents 06754d8 + 385c793 commit 47575bb
Show file tree
Hide file tree
Showing 66 changed files with 283 additions and 125 deletions.
12 changes: 6 additions & 6 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}

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

let tcx = self.tcx();
let cause = self.cause(traits::MiscObligation);
let cause = self.cause(traits::WellFormed(None));
let param_env = self.param_env;
let depth = self.recursion_depth;

Expand Down Expand Up @@ -444,7 +444,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let predicate =
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth(
cause,
self.recursion_depth,
Expand All @@ -456,7 +456,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let resolved = self.infcx.shallow_resolve(infer);
// the `InferConst` changed, meaning that we made progress.
if resolved != infer {
let cause = self.cause(traits::MiscObligation);
let cause = self.cause(traits::WellFormed(None));

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

if !defer_to_coercion {
let cause = self.cause(traits::MiscObligation);
let cause = self.cause(traits::WellFormed(None));
let component_traits = data.auto_traits().chain(data.principal_def_id());
let tcx = self.tcx();
self.out.extend(component_traits.map(|did| {
Expand Down Expand Up @@ -678,7 +678,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let ty = self.infcx.shallow_resolve(ty);
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved, but we've made progress.
let cause = self.cause(traits::MiscObligation);
let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth(
cause,
self.recursion_depth,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

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

output
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

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

Expand Down Expand Up @@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_wf_obligation(
c.into(),
self.tcx.hir().span(ast_c.hir_id),
ObligationCauseCode::MiscObligation,
ObligationCauseCode::WellFormed(None),
);
c
}
Expand All @@ -544,7 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_wf_obligation(
c.into(),
self.tcx.hir().span(ast_c.hir_id),
ObligationCauseCode::MiscObligation,
ObligationCauseCode::WellFormed(None),
);
c
}
Expand Down Expand Up @@ -607,7 +607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for arg in substs.iter().filter(|arg| {
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
}) {
self.register_wf_obligation(arg, expr.span, traits::MiscObligation);
self.register_wf_obligation(arg, expr.span, traits::WellFormed(None));
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// the function type must also be well-formed (this is not
// implied by the substs being well-formed because of inherent
// impls and late-bound regions - see issue #28609).
self.register_wf_obligation(fty.into(), self.span, traits::MiscObligation);
self.register_wf_obligation(fty.into(), self.span, traits::WellFormed(None));
}

///////////////////////////////////////////////////////////////////////////
Expand Down
51 changes: 39 additions & 12 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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,
})
Expand Down Expand Up @@ -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()
Expand All @@ -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!(
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
fcx.register_bound(
item_ty,
tcx.require_lang_item(LangItem::Sized, None),
traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
traits::ObligationCause::new(ty_span, fcx.body_id, traits::WellFormed(None)),
);
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn diagnostic_hir_wf_check<'tcx>(
let cause = traits::ObligationCause::new(
ty.span,
self.hir_id,
traits::ObligationCauseCode::MiscObligation,
traits::ObligationCauseCode::WellFormed(None),
);
fulfill.register_predicate_obligation(
&infcx,
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/associated-item/associated-item-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `mispellable` found for enum `
--> $DIR/associated-item-enum.rs:17:11
|
LL | enum Enum { Variant }
| ---- variant or associated item `mispellable` not found for this enum
| --------- variant or associated item `mispellable` not found for this enum
...
LL | Enum::mispellable();
| ^^^^^^^^^^^
Expand All @@ -14,7 +14,7 @@ error[E0599]: no variant or associated item named `mispellable_trait` found for
--> $DIR/associated-item-enum.rs:18:11
|
LL | enum Enum { Variant }
| ---- variant or associated item `mispellable_trait` not found for this enum
| --------- variant or associated item `mispellable_trait` not found for this enum
...
LL | Enum::mispellable_trait();
| ^^^^^^^^^^^^^^^^^
Expand All @@ -26,7 +26,7 @@ error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `
--> $DIR/associated-item-enum.rs:19:11
|
LL | enum Enum { Variant }
| ---- variant or associated item `MISPELLABLE` not found for this enum
| --------- variant or associated item `MISPELLABLE` not found for this enum
...
LL | Enum::MISPELLABLE;
| ^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/pin-needed-to-poll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `poll` found for struct `Sleep` in the current sco
--> $DIR/pin-needed-to-poll.rs:42:20
|
LL | struct Sleep;
| ----- method `poll` not found for this struct
| ------------ method `poll` not found for this struct
...
LL | self.sleep.poll(cx)
| ^^^^ method not found in `Sleep`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/bogus-tag.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Hsl` found for enum `Color` i
--> $DIR/bogus-tag.rs:7:16
|
LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
| ----- variant or associated item `Hsl` not found for this enum
| ---------- variant or associated item `Hsl` not found for this enum
...
LL | Color::Hsl(h, s, l) => { println!("hsl"); }
| ^^^ variant or associated item not found in `Color`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/confuse-field-and-method/issue-18343.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
--> $DIR/issue-18343.rs:7:7
|
LL | struct Obj<F> where F: FnMut() -> u32 {
| --- method `closure` not found for this struct
| ------------- method `closure` not found for this struct
...
LL | o.closure();
| ^^^^^^^ field, not a method
Expand Down
22 changes: 11 additions & 11 deletions src/test/ui/confuse-field-and-method/issue-2392.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
--> $DIR/issue-2392.rs:36:15
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `closure` not found for this struct
| ------------- method `closure` not found for this struct
...
LL | o_closure.closure();
| ^^^^^^^ field, not a method
Expand All @@ -16,7 +16,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren
--> $DIR/issue-2392.rs:38:15
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `not_closure` not found for this struct
| ------------- method `not_closure` not found for this struct
...
LL | o_closure.not_closure();
| ^^^^^^^^^^^-- help: remove the arguments
Expand All @@ -27,7 +27,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
--> $DIR/issue-2392.rs:42:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `closure` not found for this struct
| ------------- method `closure` not found for this struct
...
LL | o_func.closure();
| ^^^^^^^ field, not a method
Expand All @@ -41,7 +41,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the
--> $DIR/issue-2392.rs:45:14
|
LL | struct BoxedObj {
| -------- method `boxed_closure` not found for this struct
| --------------- method `boxed_closure` not found for this struct
...
LL | boxed_fn.boxed_closure();
| ^^^^^^^^^^^^^ field, not a method
Expand All @@ -55,7 +55,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the
--> $DIR/issue-2392.rs:48:19
|
LL | struct BoxedObj {
| -------- method `boxed_closure` not found for this struct
| --------------- method `boxed_closure` not found for this struct
...
LL | boxed_closure.boxed_closure();
| ^^^^^^^^^^^^^ field, not a method
Expand All @@ -69,7 +69,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
--> $DIR/issue-2392.rs:53:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `closure` not found for this struct
| ------------- method `closure` not found for this struct
...
LL | w.wrap.closure();
| ^^^^^^^ field, not a method
Expand All @@ -83,7 +83,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren
--> $DIR/issue-2392.rs:55:12
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `not_closure` not found for this struct
| ------------- method `not_closure` not found for this struct
...
LL | w.wrap.not_closure();
| ^^^^^^^^^^^-- help: remove the arguments
Expand All @@ -94,7 +94,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc
--> $DIR/issue-2392.rs:58:24
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
| --- method `closure` not found for this struct
| ------------- method `closure` not found for this struct
...
LL | check_expression().closure();
| ^^^^^^^ field, not a method
Expand All @@ -108,7 +108,7 @@ error[E0599]: no method named `f1` found for struct `FuncContainer` in the curre
--> $DIR/issue-2392.rs:64:31
|
LL | struct FuncContainer {
| ------------- method `f1` not found for this struct
| -------------------- method `f1` not found for this struct
...
LL | (*self.container).f1(1);
| ^^ field, not a method
Expand All @@ -122,7 +122,7 @@ error[E0599]: no method named `f2` found for struct `FuncContainer` in the curre
--> $DIR/issue-2392.rs:65:31
|
LL | struct FuncContainer {
| ------------- method `f2` not found for this struct
| -------------------- method `f2` not found for this struct
...
LL | (*self.container).f2(1);
| ^^ field, not a method
Expand All @@ -136,7 +136,7 @@ error[E0599]: no method named `f3` found for struct `FuncContainer` in the curre
--> $DIR/issue-2392.rs:66:31
|
LL | struct FuncContainer {
| ------------- method `f3` not found for this struct
| -------------------- method `f3` not found for this struct
...
LL | (*self.container).f3(1);
| ^^ field, not a method
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/confuse-field-and-method/issue-32128.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `example` found for struct `Example` in the curren
--> $DIR/issue-32128.rs:12:10
|
LL | struct Example {
| ------- method `example` not found for this struct
| -------------- method `example` not found for this struct
...
LL | demo.example(1);
| ^^^^^^^ field, not a method
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/confuse-field-and-method/private-field.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `dog_age` found for struct `Dog` in the current sc
--> $DIR/private-field.rs:16:23
|
LL | pub struct Dog {
| --- method `dog_age` not found for this struct
| -------------- method `dog_age` not found for this struct
...
LL | let dog_age = dog.dog_age();
| ^^^^^^^ private field, not a method
Expand Down
Loading

0 comments on commit 47575bb

Please sign in to comment.