mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 18:23:49 +00:00
Suggest box/pin/arc ing receiver on method calls
This commit is contained in:
parent
2917eda69d
commit
6f2d8a018e
@ -973,7 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
error: MethodError<'tcx>,
|
||||
) {
|
||||
let rcvr = &args[0];
|
||||
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
|
||||
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t, pre: &str, post: &str| {
|
||||
if let Some(new_rcvr_t) = new_rcvr_t {
|
||||
if let Ok(pick) = self.lookup_probe(
|
||||
span,
|
||||
@ -986,11 +986,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Make sure the method is defined for the *actual* receiver:
|
||||
// we don't want to treat `Box<Self>` as a receiver if
|
||||
// it only works because of an autoderef to `&self`
|
||||
if pick.autoderefs == 0 {
|
||||
if pick.autoderefs == 0
|
||||
// We don't want to suggest a container type when the missing method is
|
||||
// `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
|
||||
// far from what the user really wants.
|
||||
&& Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
|
||||
{
|
||||
err.span_label(
|
||||
pick.item.ident.span,
|
||||
&format!("the method is available for `{}` here", new_rcvr_t),
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
"consider wrapping the receiver expression with the appropriate type",
|
||||
vec![
|
||||
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
|
||||
(rcvr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1008,10 +1021,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Try alternative arbitrary self types that could fulfill this call.
|
||||
// FIXME: probe for all types that *could* be arbitrary self-types, not
|
||||
// just this list.
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
|
||||
for (rcvr_t, post) in &[
|
||||
(rcvr_t, ""),
|
||||
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_t), "&mut "),
|
||||
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_t), "&"),
|
||||
] {
|
||||
for (rcvr_t, pre) in &[
|
||||
(self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox), "Box::new"),
|
||||
(self.tcx.mk_lang_item(rcvr_t, LangItem::Pin), "Pin::new"),
|
||||
(self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc), "Arc::new"),
|
||||
(self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc), "Rc::new"),
|
||||
] {
|
||||
try_alt_rcvr(&mut err, *rcvr_t, pre, post);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ pub struct MethodCallee<'tcx> {
|
||||
pub sig: ty::FnSig<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MethodError<'tcx> {
|
||||
// Did not find an applicable method, but we did find various near-misses that may work.
|
||||
NoMatch(NoMatchData<'tcx>),
|
||||
@ -66,6 +67,7 @@ pub enum MethodError<'tcx> {
|
||||
|
||||
// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
|
||||
// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
|
||||
#[derive(Debug)]
|
||||
pub struct NoMatchData<'tcx> {
|
||||
pub static_candidates: Vec<CandidateSource>,
|
||||
pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
|
||||
|
47
src/test/ui/async-await/pin-needed-to-poll.rs
Normal file
47
src/test/ui/async-await/pin-needed-to-poll.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
struct Sleep;
|
||||
|
||||
impl Future for Sleep {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Sleep {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn sleep() -> Sleep {
|
||||
Sleep
|
||||
}
|
||||
|
||||
|
||||
struct MyFuture {
|
||||
sleep: Sleep,
|
||||
}
|
||||
|
||||
impl MyFuture {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
sleep: sleep(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for MyFuture {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.sleep.poll(cx)
|
||||
//~^ ERROR no method named `poll` found for struct `Sleep` in the current scope
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
25
src/test/ui/async-await/pin-needed-to-poll.stderr
Normal file
25
src/test/ui/async-await/pin-needed-to-poll.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error[E0599]: no method named `poll` found for struct `Sleep` in the current scope
|
||||
--> $DIR/pin-needed-to-poll.rs:42:20
|
||||
|
|
||||
LL | struct Sleep;
|
||||
| ------------- method `poll` not found for this
|
||||
...
|
||||
LL | self.sleep.poll(cx)
|
||||
| ^^^^ method not found in `Sleep`
|
||||
|
|
||||
::: $SRC_DIR/core/src/future/future.rs:LL:COL
|
||||
|
|
||||
LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
|
||||
| ---- the method is available for `Pin<&mut Sleep>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `poll`, perhaps you need to implement it:
|
||||
candidate #1: `Future`
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Pin::new(&mut self.sleep).poll(cx)
|
||||
| ^^^^^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -6,14 +6,6 @@ LL | struct Foo {
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Foo>` here
|
||||
| the method is available for `Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -12,14 +12,6 @@ LL | struct NotClone;
|
||||
...
|
||||
LL | Bar::<NotClone> { x: 1 }.clone();
|
||||
| ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Bar<NotClone>>` here
|
||||
| the method is available for `Rc<Bar<NotClone>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`NotClone: Clone`
|
||||
|
@ -6,14 +6,6 @@ LL | struct C {
|
||||
...
|
||||
LL | let _d = c.clone();
|
||||
| ^^^^^ method not found in `C`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<C>` here
|
||||
| the method is available for `Rc<C>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -8,14 +8,6 @@ LL | let _ = Struct::<A>::new().clone();
|
||||
|
|
||||
LL | pub struct Struct<A>(A);
|
||||
| ------------------------ doesn't satisfy `Struct<A>: Clone`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Struct<A>>` here
|
||||
| the method is available for `Rc<Struct<A>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`A: Clone`
|
||||
|
@ -3,14 +3,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco
|
||||
|
|
||||
LL | let _z = (*y).clone();
|
||||
| ^^^^^ method not found in `c_void`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<c_void>` here
|
||||
| the method is available for `Rc<c_void>` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,14 +6,6 @@ LL | struct Foo {
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Foo>` here
|
||||
| the method is available for `Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -9,6 +9,11 @@ LL | fn foo(self: Box<Self>) {}
|
||||
...
|
||||
LL | A.foo();
|
||||
| ^^^ method not found in `A`
|
||||
|
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Box::new(A).foo();
|
||||
| ^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | struct A;
|
||||
...
|
||||
LL | A.foo()
|
||||
| ^^^ method not found in `A`
|
||||
|
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Box::new(A).foo()
|
||||
| ^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:36:11
|
||||
|
|
||||
LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
||||
| - ^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'a` here: `'a,`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
@ -6,14 +6,6 @@ LL | struct Qux;
|
||||
...
|
||||
LL | Qux.clone();
|
||||
| ^^^^^ method not found in `Qux`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Qux>` here
|
||||
| the method is available for `Rc<Qux>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
|
||||
|
@ -25,14 +25,6 @@ LL | struct CloneNoCopy;
|
||||
...
|
||||
LL | let w = u.clone();
|
||||
| ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<U5<CloneNoCopy>>` here
|
||||
| the method is available for `Rc<U5<CloneNoCopy>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`CloneNoCopy: Copy`
|
||||
|
@ -10,14 +10,6 @@ LL | trait Foo {
|
||||
LL | let _z = y.clone();
|
||||
| ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Box<dyn Foo>>` here
|
||||
| the method is available for `Rc<Box<dyn Foo>>` here
|
||||
|
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
LL | / pub struct Box<
|
||||
|
@ -7,14 +7,6 @@ LL | struct R {
|
||||
LL | let _j = i.clone();
|
||||
| ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Box<R>>` here
|
||||
| the method is available for `Rc<Box<R>>` here
|
||||
|
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
LL | / pub struct Box<
|
||||
|
Loading…
Reference in New Issue
Block a user