Skip to content

Commit a41cb7d

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 cb59053 + 06b82ab commit a41cb7d

File tree

57 files changed

+677
-162
lines changed

Some content is hidden

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

57 files changed

+677
-162
lines changed

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,7 +2069,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20692069

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

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

21002132
let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
21012133
let mut data = data;

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

Lines changed: 53 additions & 52 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 15 additions & 3 deletions
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

Lines changed: 10 additions & 2 deletions
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 5 additions & 1 deletion
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
|
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::{
2+
future::Future,
3+
pin::Pin,
4+
marker::Unpin,
5+
task::{Context, Poll},
6+
};
7+
8+
struct Sleep(std::marker::PhantomPinned);
9+
10+
impl Future for Sleep {
11+
type Output = ();
12+
13+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
14+
Poll::Ready(())
15+
}
16+
}
17+
18+
impl Drop for Sleep {
19+
fn drop(&mut self) {}
20+
}
21+
22+
fn sleep() -> Sleep {
23+
Sleep(std::marker::PhantomPinned)
24+
}
25+
26+
27+
struct MyFuture {
28+
sleep: Sleep,
29+
}
30+
31+
impl MyFuture {
32+
fn new() -> Self {
33+
Self {
34+
sleep: sleep(),
35+
}
36+
}
37+
}
38+
39+
impl Future for MyFuture {
40+
type Output = ();
41+
42+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
43+
Pin::new(&mut self.sleep).poll(cx)
44+
//~^ ERROR `PhantomPinned` cannot be unpinned
45+
}
46+
}
47+
48+
fn main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: `PhantomPinned` cannot be unpinned
2+
--> $DIR/pin-needed-to-poll-2.rs:43:9
3+
|
4+
LL | Pin::new(&mut self.sleep).poll(cx)
5+
| ^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`
6+
|
7+
= note: consider using `Box::pin`
8+
note: required because it appears within the type `Sleep`
9+
--> $DIR/pin-needed-to-poll-2.rs:8:8
10+
|
11+
LL | struct Sleep(std::marker::PhantomPinned);
12+
| ^^^^^
13+
= note: required by `Pin::<P>::new`
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/block-result/issue-22645.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ LL | b + 3
66
|
77
= help: the following implementations were found:
88
<f64 as Scalar>
9-
= note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
9+
note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
10+
--> $DIR/issue-22645.rs:8:19
11+
|
12+
LL | impl<RHS: Scalar> Add <RHS> for Bob {
13+
| ^^^^^^^^^ ^^^
1014

1115
error[E0308]: mismatched types
1216
--> $DIR/issue-22645.rs:15:3

src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ LL | impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
99
LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
1010
| ---- required by this bound in `RequiresRequiresShareAndSend`
1111
|
12-
= note: required because it appears within the type `X<T>`
12+
note: required because it appears within the type `X<T>`
13+
--> $DIR/builtin-superkinds-in-metadata.rs:9:8
14+
|
15+
LL | struct X<T>(T);
16+
| ^
1317
help: consider further restricting this bound
1418
|
1519
LL | impl <T:Sync+'static + std::marker::Send> RequiresRequiresShareAndSend for X<T> { }

0 commit comments

Comments
 (0)