From 7d21972579011cf97d9d439699efae6244219835 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 29 Mar 2021 21:49:58 +0800 Subject: Wrap non-pre code blocks Fix #83550 regression --- src/librustdoc/html/static/rustdoc.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 6c90fd7c9ee..f5a034a0d24 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -424,7 +424,9 @@ nav.sub { text-overflow: ellipsis; margin: 0; } -.docblock-short code { +/* Wrap non-pre code blocks (`text`) but not (```text```). */ +.docblock > :not(pre) > code, +.docblock-short > :not(pre) > code { white-space: pre-wrap; } -- cgit 1.4.1-3-g733a5 From 180ac802728c9983bd6e8d1e201a34aa981396d6 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 29 Mar 2021 13:53:10 -0700 Subject: Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/doc/book b/src/doc/book index fc2f690fc16..b54090a99ec 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit fc2f690fc16592abbead2360cfc0a42f5df78052 +Subproject commit b54090a99ec7c4b46a5203a9c927fdbc311bb1f5 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index f61685755fa..d3f2ace94d5 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit f61685755fad7d3b88b4645adfbf461d500563a2 +Subproject commit d3f2ace94d51610cf3e3c265705bb8416d37f8e4 diff --git a/src/doc/reference b/src/doc/reference index d10a0af8dca..fd97729e2d8 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit d10a0af8dca25d9d548ca6a369fd66ad06acb3c9 +Subproject commit fd97729e2d82f8b08d68a31c9bfdf0c37a7fd542 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index eead22c6c03..29d91f591c9 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit eead22c6c030fa4f3a167d1798658c341199e2ae +Subproject commit 29d91f591c90dd18fdca6d23f1a9caf9c139d0d7 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 67ebd4b55db..0687daac289 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 67ebd4b55dba44edfc351621cef6e5e758169c55 +Subproject commit 0687daac28939c476df51778f5a1d1aff1a3fddf -- cgit 1.4.1-3-g733a5 From edacd0f9814e1cc50d7f91b7bcd4337563f2bd5e Mon Sep 17 00:00:00 2001 From: JohnTitor Date: Tue, 30 Mar 2021 03:31:53 +0900 Subject: Add a regression test for issue-82865 --- src/test/ui/resolve/issue-82865.rs | 13 +++++++++++++ src/test/ui/resolve/issue-82865.stderr | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/resolve/issue-82865.rs create mode 100644 src/test/ui/resolve/issue-82865.stderr (limited to 'src') diff --git a/src/test/ui/resolve/issue-82865.rs b/src/test/ui/resolve/issue-82865.rs new file mode 100644 index 00000000000..07d88c413bf --- /dev/null +++ b/src/test/ui/resolve/issue-82865.rs @@ -0,0 +1,13 @@ +// Regression test for #82865. + +#![feature(decl_macro)] + +use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`? + +macro mac () { + Box::z //~ ERROR: no function or associated item +} + +fn main() { + mac!(); +} diff --git a/src/test/ui/resolve/issue-82865.stderr b/src/test/ui/resolve/issue-82865.stderr new file mode 100644 index 00000000000..027d7a0e0e4 --- /dev/null +++ b/src/test/ui/resolve/issue-82865.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: maybe a missing crate `x`? + --> $DIR/issue-82865.rs:5:5 + | +LL | use x::y::z; + | ^ maybe a missing crate `x`? + +error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope + --> $DIR/issue-82865.rs:8:10 + | +LL | Box::z + | ^ function or associated item not found in `Box<_, _>` +... +LL | mac!(); + | ------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. -- cgit 1.4.1-3-g733a5 From 6f2d8a018e4ff062032608a30615129230490b0d Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 29 Mar 2021 18:14:44 -0700 Subject: Suggest box/pin/arc ing receiver on method calls --- compiler/rustc_typeck/src/check/expr.rs | 35 +++++++++++++--- compiler/rustc_typeck/src/check/method/mod.rs | 2 + src/test/ui/async-await/pin-needed-to-poll.rs | 47 ++++++++++++++++++++++ src/test/ui/async-await/pin-needed-to-poll.stderr | 25 ++++++++++++ src/test/ui/copy-a-resource.stderr | 8 ---- .../ui/derives/derive-assoc-type-not-impl.stderr | 8 ---- src/test/ui/issues/issue-2823.stderr | 8 ---- src/test/ui/issues/issue-69725.stderr | 8 ---- src/test/ui/non-copyable-void.stderr | 8 ---- src/test/ui/noncopyable-class.stderr | 8 ---- .../point-at-arbitrary-self-type-method.stderr | 5 +++ ...oint-at-arbitrary-self-type-trait-method.stderr | 5 +++ .../missing-lifetimes-in-signature.nll.stderr | 11 ----- .../explicitly-unimplemented-error-message.stderr | 8 ---- src/test/ui/union/union-derive-clone.stderr | 8 ---- src/test/ui/unique-object-noncopyable.stderr | 8 ---- src/test/ui/unique-pinned-nocopy.stderr | 8 ---- 17 files changed, 113 insertions(+), 97 deletions(-) create mode 100644 src/test/ui/async-await/pin-needed-to-poll.rs create mode 100644 src/test/ui/async-await/pin-needed-to-poll.stderr delete mode 100644 src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr (limited to 'src') diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8951c08bd33..9a2e933eb0b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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` 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(); } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index d6fa6bf0067..c74fd25f76d 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -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, pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, diff --git a/src/test/ui/async-await/pin-needed-to-poll.rs b/src/test/ui/async-await/pin-needed-to-poll.rs new file mode 100644 index 00000000000..0d1fe684f60 --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll.rs @@ -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 { + 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.sleep.poll(cx) + //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope + } +} + +fn main() {} diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr new file mode 100644 index 00000000000..0e3716d6156 --- /dev/null +++ b/src/test/ui/async-await/pin-needed-to-poll.stderr @@ -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; + | ---- 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`. diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index 36cf57bd3c5..79095452f9d 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -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` here - | the method is available for `Rc` 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: diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index ffee7004f8f..fd993d0f9d8 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -12,14 +12,6 @@ LL | struct NotClone; ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc>` here - | the method is available for `Rc>` here | = note: the following trait bounds were not satisfied: `NotClone: Clone` diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index e044352e954..b3bc946292f 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -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` here - | the method is available for `Rc` 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: diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr index 48c71d76af0..4dd6b4bbb68 100644 --- a/src/test/ui/issues/issue-69725.stderr +++ b/src/test/ui/issues/issue-69725.stderr @@ -8,14 +8,6 @@ LL | let _ = Struct::::new().clone(); | LL | pub struct Struct(A); | ------------------------ doesn't satisfy `Struct: Clone` - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc>` here - | the method is available for `Rc>` here | = note: the following trait bounds were not satisfied: `A: Clone` diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr index 8395a3a0563..99af04e7cd9 100644 --- a/src/test/ui/non-copyable-void.stderr +++ b/src/test/ui/non-copyable-void.stderr @@ -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` here - | the method is available for `Rc` here error: aborting due to previous error diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index b8e467d8402..4674c16eb43 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -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` here - | the method is available for `Rc` 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: diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr index 2954a499c18..b804ddfb024 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -9,6 +9,11 @@ LL | fn foo(self: Box) {} ... 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 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 89fe84c0d2d..e1ed0e42f98 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -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 diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr deleted file mode 100644 index 916a6c2bf12..00000000000 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/missing-lifetimes-in-signature.rs:36:11 - | -LL | fn baz(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`. diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr index d39daaba206..01e36a4a62a 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -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` here - | the method is available for `Rc` 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 diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index a793bf58d23..546394664df 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -25,14 +25,6 @@ LL | struct CloneNoCopy; ... LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc>` here - | the method is available for `Rc>` here | = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 4bbacfc0a8b..6a355dd2562 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -10,14 +10,6 @@ LL | trait Foo { LL | let _z = y.clone(); | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc>` here - | the method is available for `Rc>` here - | ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | LL | / pub struct Box< diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index dd0b7fc5489..a4421bcf809 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -7,14 +7,6 @@ LL | struct R { LL | let _j = i.clone(); | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc>` here - | the method is available for `Rc>` here - | ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | LL | / pub struct Box< -- cgit 1.4.1-3-g733a5 From 0195f8d3751ed2c14c405686c41064c4c41baa39 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 29 Mar 2021 19:53:48 -0700 Subject: Hide unnecessary reference to trait When the problem for a method not being found in its receiver is due to arbitrary self-types, we don't want to mention importing or implementing the trait, instead we suggest wrapping. --- compiler/rustc_typeck/src/check/expr.rs | 96 ++++------------------- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 6 +- compiler/rustc_typeck/src/check/method/suggest.rs | 87 +++++++++++++++++--- compiler/rustc_typeck/src/check/pat.rs | 2 +- src/test/ui/async-await/pin-needed-to-poll.stderr | 3 - 5 files changed, 98 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 9a2e933eb0b..30d60514063 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -6,7 +6,7 @@ use crate::astconv::AstConv as _; use crate::check::cast; use crate::check::coercion::CoerceMany; use crate::check::fatally_break_rust; -use crate::check::method::{probe, MethodError, SelfSource}; +use crate::check::method::SelfSource; use crate::check::report_unexpected_variant_res; use crate::check::BreakableCtxt; use crate::check::Diverges; @@ -30,7 +30,6 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -461,7 +460,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 } - fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> { + fn check_expr_path( + &self, + qpath: &'tcx hir::QPath<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span); let ty = match res { @@ -947,7 +950,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(error) => { if segment.ident.name != kw::Empty { - self.report_extended_method_error(segment, span, args, rcvr_t, error); + if let Some(mut err) = self.report_method_error( + span, + rcvr_t, + segment.ident, + SelfSource::MethodCall(&args[0]), + error, + Some(args), + ) { + err.emit(); + } } Err(()) } @@ -964,82 +976,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - fn report_extended_method_error( - &self, - segment: &hir::PathSegment<'_>, - span: Span, - args: &'tcx [hir::Expr<'tcx>], - rcvr_t: Ty<'tcx>, - error: MethodError<'tcx>, - ) { - let rcvr = &args[0]; - 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, - segment.ident, - new_rcvr_t, - rcvr, - probe::ProbeScope::AllTraits, - ) { - debug!("try_alt_rcvr: pick candidate {:?}", pick); - // Make sure the method is defined for the *actual* receiver: - // we don't want to treat `Box` as a receiver if - // it only works because of an autoderef to `&self` - 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, - ); - } - } - } - }; - - if let Some(mut err) = self.report_method_error( - span, - rcvr_t, - segment.ident, - SelfSource::MethodCall(rcvr), - error, - Some(args), - ) { - if let ty::Adt(..) = rcvr_t.kind() { - // 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. - 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(); - } - } - fn check_expr_cast( &self, e: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index e64d8367676..a7a412f06be 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -905,12 +905,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. - pub fn resolve_ty_and_res_ufcs<'b>( + pub fn resolve_ty_and_res_ufcs( &self, - qpath: &'b QPath<'b>, + qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, - ) -> (Res, Option>, &'b [hir::PathSegment<'b>]) { + ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 13757ac4132..72eff009473 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -68,12 +68,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn report_method_error<'b>( + pub fn report_method_error( &self, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> Option> { @@ -323,8 +323,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( lit.span, &format!( - "you must specify a concrete type for \ - this numeric value, like `{}`", + "you must specify a concrete type for this numeric value, \ + like `{}`", concrete_type ), format!("{}_{}", snippet, concrete_type), @@ -975,17 +975,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_traits_to_import<'b>( + fn suggest_traits_to_import( &self, err: &mut DiagnosticBuilder<'_>, span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, - source: SelfSource<'b>, + source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], ) { - if self.suggest_valid_traits(err, valid_out_of_scope_traits) { + let mut alt_rcvr_sugg = false; + if let SelfSource::MethodCall(rcvr) = source { + info!(?span, ?item_name, ?rcvr_ty, ?rcvr); + if let ty::Adt(..) = rcvr_ty.kind() { + // 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. + for (rcvr_ty, post) in &[ + (rcvr_ty, ""), + (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "), + (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"), + ] { + for (rcvr_ty, pre) in &[ + (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"), + (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"), + (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"), + ] { + if let Some(new_rcvr_t) = *rcvr_ty { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + debug!("try_alt_rcvr: pick candidate {:?}", pick); + // Make sure the method is defined for the *actual* receiver: + // we don't want to treat `Box` as a receiver if + // it only works because of an autoderef to `&self` + 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, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; + } + } + } + } + } + } + } + if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } @@ -1075,6 +1136,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the method might not be found because of this arbitrary self type", ); } + if alt_rcvr_sugg { + return; + } if !candidates.is_empty() { // Sort from most relevant to least relevant. @@ -1284,7 +1348,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks whether there is a local type somewhere in the chain of /// autoderefs of `rcvr_ty`. - fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool { + fn type_derefs_to_local( + &self, + span: Span, + rcvr_ty: Ty<'tcx>, + source: SelfSource<'tcx>, + ) -> bool { fn is_local(ty: Ty<'_>) -> bool { match ty.kind() { ty::Adt(def, _) => def.did.is_local(), @@ -1310,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum SelfSource<'a> { QPath(&'a hir::Ty<'a>), MethodCall(&'a hir::Expr<'a> /* rcvr */), diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 79c544bd386..53593b9bab4 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -861,7 +861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_tuple_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &'tcx hir::QPath<'tcx>, subpats: &'tcx [&'tcx Pat<'tcx>], ddpos: Option, expected: Ty<'tcx>, diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr index 0e3716d6156..0756a4d59c1 100644 --- a/src/test/ui/async-await/pin-needed-to-poll.stderr +++ b/src/test/ui/async-await/pin-needed-to-poll.stderr @@ -12,9 +12,6 @@ LL | self.sleep.poll(cx) LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; | ---- 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) -- cgit 1.4.1-3-g733a5