Skip to content

Commit a113240

Browse files
authored
Rollup merge of #83689 - estebank:cool-bears-hot-tip, r=davidtwco
Add more info for common trait resolution and async/await errors * Suggest `Pin::new`/`Box::new`/`Arc::new`/`Box::pin` in more cases * Point at `impl` and type defs introducing requirements on E0277
2 parents cbe3eba + 64e6288 commit a113240

File tree

62 files changed

+813
-195
lines changed

Some content is hidden

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

62 files changed

+813
-195
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+87-14
Original file line numberDiff line numberDiff line change
@@ -2070,7 +2070,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20702070

20712071
// Don't print the tuple of capture types
20722072
if !is_upvar_tys_infer_tuple {
2073-
err.note(&format!("required because it appears within the type `{}`", ty));
2073+
let msg = format!("required because it appears within the type `{}`", ty);
2074+
match ty.kind() {
2075+
ty::Adt(def, _) => match self.tcx.opt_item_name(def.did) {
2076+
Some(ident) => err.span_note(ident.span, &msg),
2077+
None => err.note(&msg),
2078+
},
2079+
_ => err.note(&msg),
2080+
};
20742081
}
20752082

20762083
obligated_types.push(ty);
@@ -2092,11 +2099,36 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20922099
ObligationCauseCode::ImplDerivedObligation(ref data) => {
20932100
let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
20942101
let parent_def_id = parent_trait_ref.def_id();
2095-
err.note(&format!(
2102+
let msg = format!(
20962103
"required because of the requirements on the impl of `{}` for `{}`",
20972104
parent_trait_ref.print_only_trait_path(),
20982105
parent_trait_ref.skip_binder().self_ty()
2099-
));
2106+
);
2107+
let mut candidates = vec![];
2108+
self.tcx.for_each_relevant_impl(
2109+
parent_def_id,
2110+
parent_trait_ref.self_ty().skip_binder(),
2111+
|impl_def_id| {
2112+
candidates.push(impl_def_id);
2113+
},
2114+
);
2115+
match &candidates[..] {
2116+
[def_id] => match self.tcx.hir().get_if_local(*def_id) {
2117+
Some(Node::Item(hir::Item {
2118+
kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
2119+
..
2120+
})) => {
2121+
let mut spans = Vec::with_capacity(2);
2122+
if let Some(trait_ref) = of_trait {
2123+
spans.push(trait_ref.path.span);
2124+
}
2125+
spans.push(self_ty.span);
2126+
err.span_note(spans, &msg)
2127+
}
2128+
_ => err.note(&msg),
2129+
},
2130+
_ => err.note(&msg),
2131+
};
21002132

21012133
let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
21022134
let mut data = data;
@@ -2147,19 +2179,60 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
21472179
)
21482180
});
21492181
}
2150-
ObligationCauseCode::CompareImplMethodObligation { .. } => {
2151-
err.note(&format!(
2152-
"the requirement `{}` appears on the impl method but not on the corresponding \
2153-
trait method",
2154-
predicate
2155-
));
2182+
ObligationCauseCode::CompareImplMethodObligation {
2183+
item_name,
2184+
trait_item_def_id,
2185+
..
2186+
} => {
2187+
let msg = format!(
2188+
"the requirement `{}` appears on the impl method `{}` but not on the \
2189+
corresponding trait method",
2190+
predicate, item_name,
2191+
);
2192+
let sp = self
2193+
.tcx
2194+
.opt_item_name(trait_item_def_id)
2195+
.map(|i| i.span)
2196+
.unwrap_or_else(|| self.tcx.def_span(trait_item_def_id));
2197+
let mut assoc_span: MultiSpan = sp.into();
2198+
assoc_span.push_span_label(
2199+
sp,
2200+
format!("this trait method doesn't have the requirement `{}`", predicate),
2201+
);
2202+
if let Some(ident) = self
2203+
.tcx
2204+
.opt_associated_item(trait_item_def_id)
2205+
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
2206+
{
2207+
assoc_span.push_span_label(ident.span, "in this trait".into());
2208+
}
2209+
err.span_note(assoc_span, &msg);
21562210
}
2157-
ObligationCauseCode::CompareImplTypeObligation { .. } => {
2158-
err.note(&format!(
2159-
"the requirement `{}` appears on the associated impl type but not on the \
2211+
ObligationCauseCode::CompareImplTypeObligation {
2212+
item_name, trait_item_def_id, ..
2213+
} => {
2214+
let msg = format!(
2215+
"the requirement `{}` appears on the associated impl type `{}` but not on the \
21602216
corresponding associated trait type",
2161-
predicate
2162-
));
2217+
predicate, item_name,
2218+
);
2219+
let sp = self.tcx.def_span(trait_item_def_id);
2220+
let mut assoc_span: MultiSpan = sp.into();
2221+
assoc_span.push_span_label(
2222+
sp,
2223+
format!(
2224+
"this trait associated type doesn't have the requirement `{}`",
2225+
predicate,
2226+
),
2227+
);
2228+
if let Some(ident) = self
2229+
.tcx
2230+
.opt_associated_item(trait_item_def_id)
2231+
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
2232+
{
2233+
assoc_span.push_span_label(ident.span, "in this trait".into());
2234+
}
2235+
err.span_note(assoc_span, &msg);
21632236
}
21642237
ObligationCauseCode::CompareImplConstObligation => {
21652238
err.note(&format!(

compiler/rustc_typeck/src/check/method/suggest.rs

+53-52
Original file line numberDiff line numberDiff line change
@@ -987,59 +987,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
987987
) {
988988
let mut alt_rcvr_sugg = false;
989989
if let SelfSource::MethodCall(rcvr) = source {
990-
info!(?span, ?item_name, ?rcvr_ty, ?rcvr);
991-
if let ty::Adt(..) = rcvr_ty.kind() {
992-
// Try alternative arbitrary self types that could fulfill this call.
993-
// FIXME: probe for all types that *could* be arbitrary self-types, not
994-
// just this list.
995-
for (rcvr_ty, post) in &[
996-
(rcvr_ty, ""),
997-
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
998-
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
990+
debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
991+
// Try alternative arbitrary self types that could fulfill this call.
992+
// FIXME: probe for all types that *could* be arbitrary self-types, not
993+
// just this list.
994+
for (rcvr_ty, post) in &[
995+
(rcvr_ty, ""),
996+
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
997+
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
998+
] {
999+
for (rcvr_ty, pre) in &[
1000+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1001+
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1002+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1003+
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
9991004
] {
1000-
for (rcvr_ty, pre) in &[
1001-
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1002-
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1003-
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1004-
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1005-
] {
1006-
if let Some(new_rcvr_t) = *rcvr_ty {
1007-
if let Ok(pick) = self.lookup_probe(
1008-
span,
1009-
item_name,
1010-
new_rcvr_t,
1011-
rcvr,
1012-
crate::check::method::probe::ProbeScope::AllTraits,
1013-
) {
1014-
debug!("try_alt_rcvr: pick candidate {:?}", pick);
1015-
// Make sure the method is defined for the *actual* receiver:
1016-
// we don't want to treat `Box<Self>` as a receiver if
1017-
// it only works because of an autoderef to `&self`
1018-
if pick.autoderefs == 0
1019-
// We don't want to suggest a container type when the missing method is
1020-
// `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
1021-
// far from what the user really wants.
1022-
&& Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
1023-
{
1024-
err.span_label(
1025-
pick.item.ident.span,
1026-
&format!(
1027-
"the method is available for `{}` here",
1028-
new_rcvr_t
1029-
),
1030-
);
1031-
err.multipart_suggestion(
1032-
"consider wrapping the receiver expression with the \
1033-
appropriate type",
1034-
vec![
1035-
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1036-
(rcvr.span.shrink_to_hi(), ")".to_string()),
1037-
],
1038-
Applicability::MaybeIncorrect,
1039-
);
1040-
// We don't care about the other suggestions.
1041-
alt_rcvr_sugg = true;
1042-
}
1005+
if let Some(new_rcvr_t) = *rcvr_ty {
1006+
if let Ok(pick) = self.lookup_probe(
1007+
span,
1008+
item_name,
1009+
new_rcvr_t,
1010+
rcvr,
1011+
crate::check::method::probe::ProbeScope::AllTraits,
1012+
) {
1013+
debug!("try_alt_rcvr: pick candidate {:?}", pick);
1014+
let did = Some(pick.item.container.id());
1015+
// We don't want to suggest a container type when the missing
1016+
// method is `.clone()` or `.deref()` otherwise we'd suggest
1017+
// `Arc::new(foo).clone()`, which is far from what the user wants.
1018+
let skip = [
1019+
self.tcx.lang_items().clone_trait(),
1020+
self.tcx.lang_items().deref_trait(),
1021+
self.tcx.lang_items().deref_mut_trait(),
1022+
self.tcx.lang_items().drop_trait(),
1023+
]
1024+
.contains(&did);
1025+
// Make sure the method is defined for the *actual* receiver: we don't
1026+
// want to treat `Box<Self>` as a receiver if it only works because of
1027+
// an autoderef to `&self`
1028+
if pick.autoderefs == 0 && !skip {
1029+
err.span_label(
1030+
pick.item.ident.span,
1031+
&format!("the method is available for `{}` here", new_rcvr_t),
1032+
);
1033+
err.multipart_suggestion(
1034+
"consider wrapping the receiver expression with the \
1035+
appropriate type",
1036+
vec![
1037+
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1038+
(rcvr.span.shrink_to_hi(), ")".to_string()),
1039+
],
1040+
Applicability::MaybeIncorrect,
1041+
);
1042+
// We don't care about the other suggestions.
1043+
alt_rcvr_sugg = true;
10431044
}
10441045
}
10451046
}

library/core/src/marker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
765765
/// [`pin` module]: crate::pin
766766
#[stable(feature = "pin", since = "1.33.0")]
767767
#[rustc_on_unimplemented(
768-
on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
768+
note = "consider using `Box::pin`",
769769
message = "`{Self}` cannot be unpinned"
770770
)]
771771
#[lang = "unpin"]

src/test/ui/associated-types/impl-wf-cycle-1.stderr

+15-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ LL | |
1010
LL | | }
1111
| |_^
1212
|
13-
= note: required because of the requirements on the impl of `Grault` for `(T,)`
13+
note: required because of the requirements on the impl of `Grault` for `(T,)`
14+
--> $DIR/impl-wf-cycle-1.rs:15:17
15+
|
16+
LL | impl<T: Grault> Grault for (T,)
17+
| ^^^^^^ ^^^^
1418
= note: 1 redundant requirements hidden
1519
= note: required because of the requirements on the impl of `Grault` for `(T,)`
1620

@@ -20,7 +24,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
2024
LL | type A = ();
2125
| ^^^^^^^^^^^^
2226
|
23-
= note: required because of the requirements on the impl of `Grault` for `(T,)`
27+
note: required because of the requirements on the impl of `Grault` for `(T,)`
28+
--> $DIR/impl-wf-cycle-1.rs:15:17
29+
|
30+
LL | impl<T: Grault> Grault for (T,)
31+
| ^^^^^^ ^^^^
2432
= note: 1 redundant requirements hidden
2533
= note: required because of the requirements on the impl of `Grault` for `(T,)`
2634

@@ -30,7 +38,11 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
3038
LL | type B = bool;
3139
| ^^^^^^^^^^^^^^
3240
|
33-
= note: required because of the requirements on the impl of `Grault` for `(T,)`
41+
note: required because of the requirements on the impl of `Grault` for `(T,)`
42+
--> $DIR/impl-wf-cycle-1.rs:15:17
43+
|
44+
LL | impl<T: Grault> Grault for (T,)
45+
| ^^^^^^ ^^^^
3446
= note: 1 redundant requirements hidden
3547
= note: required because of the requirements on the impl of `Grault` for `(T,)`
3648

src/test/ui/associated-types/impl-wf-cycle-2.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,23 @@ LL | |
1010
LL | | }
1111
| |_^
1212
|
13-
= note: required because of the requirements on the impl of `Grault` for `(T,)`
13+
note: required because of the requirements on the impl of `Grault` for `(T,)`
14+
--> $DIR/impl-wf-cycle-2.rs:7:17
15+
|
16+
LL | impl<T: Grault> Grault for (T,)
17+
| ^^^^^^ ^^^^
1418

1519
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
1620
--> $DIR/impl-wf-cycle-2.rs:11:5
1721
|
1822
LL | type A = ();
1923
| ^^^^^^^^^^^^
2024
|
21-
= note: required because of the requirements on the impl of `Grault` for `(T,)`
25+
note: required because of the requirements on the impl of `Grault` for `(T,)`
26+
--> $DIR/impl-wf-cycle-2.rs:7:17
27+
|
28+
LL | impl<T: Grault> Grault for (T,)
29+
| ^^^^^^ ^^^^
2230

2331
error: aborting due to 2 previous errors
2432

src/test/ui/associated-types/issue-44153.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ LL | fn visit() {}
77
LL | <() as Visit>::visit();
88
| ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()`
99
|
10-
= note: required because of the requirements on the impl of `Visit` for `()`
10+
note: required because of the requirements on the impl of `Visit` for `()`
11+
--> $DIR/issue-44153.rs:13:10
12+
|
13+
LL | impl<'a> Visit for () where
14+
| ^^^^^ ^^
1115

1216
error: aborting due to previous error
1317

src/test/ui/associated-types/issue-65774-1.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied
1313
LL | let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
1414
| ^^^^^^^ the trait `MyDisplay` is not implemented for `T`
1515
|
16-
= note: required because of the requirements on the impl of `MyDisplay` for `&mut T`
16+
note: required because of the requirements on the impl of `MyDisplay` for `&mut T`
17+
--> $DIR/issue-65774-1.rs:5:24
18+
|
19+
LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
20+
| ^^^^^^^^^ ^^^^^^^^^
1721
= note: required for the cast to the object type `dyn MyDisplay`
1822

1923
error: aborting due to 2 previous errors

src/test/ui/async-await/issue-72590-type-error-sized.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ LL | async fn frob(self) {}
1717
| ^^^^ doesn't have a size known at compile-time
1818
|
1919
= help: within `Foo`, the trait `Sized` is not implemented for `str`
20-
= note: required because it appears within the type `Foo`
20+
note: required because it appears within the type `Foo`
21+
--> $DIR/issue-72590-type-error-sized.rs:5:8
22+
|
23+
LL | struct Foo {
24+
| ^^^
2125
= help: unsized fn params are gated as an unstable feature
2226
help: function arguments must have a statically known size, borrowed types always have a known size
2327
|

0 commit comments

Comments
 (0)