Skip to content

Commit 0626919

Browse files
Do not suggest wrapping an item if it has ambiguous un-imported methods
1 parent 03a8cc7 commit 0626919

File tree

4 files changed

+65
-39
lines changed

4 files changed

+65
-39
lines changed

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

+24-13
Original file line numberDiff line numberDiff line change
@@ -1485,27 +1485,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14851485
(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
14861486
(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
14871487
] {
1488-
if let Ok(pick) = self.lookup_probe(
1488+
match self.lookup_probe(
14891489
span,
14901490
item_name,
14911491
*rcvr_ty,
14921492
rcvr,
14931493
crate::check::method::probe::ProbeScope::AllTraits,
14941494
) {
1495-
// If the method is defined for the receiver we have, it likely wasn't `use`d.
1496-
// We point at the method, but we just skip the rest of the check for arbitrary
1497-
// self types and rely on the suggestion to `use` the trait from
1498-
// `suggest_valid_traits`.
1499-
let did = Some(pick.item.container.id());
1500-
let skip = skippable.contains(&did);
1501-
if pick.autoderefs == 0 && !skip {
1502-
err.span_label(
1503-
pick.item.ident(self.tcx).span,
1504-
&format!("the method is available for `{}` here", rcvr_ty),
1505-
);
1495+
Ok(pick) => {
1496+
// If the method is defined for the receiver we have, it likely wasn't `use`d.
1497+
// We point at the method, but we just skip the rest of the check for arbitrary
1498+
// self types and rely on the suggestion to `use` the trait from
1499+
// `suggest_valid_traits`.
1500+
let did = Some(pick.item.container.id());
1501+
let skip = skippable.contains(&did);
1502+
if pick.autoderefs == 0 && !skip {
1503+
err.span_label(
1504+
pick.item.ident(self.tcx).span,
1505+
&format!("the method is available for `{}` here", rcvr_ty),
1506+
);
1507+
}
1508+
break;
15061509
}
1507-
break;
1510+
Err(MethodError::Ambiguity(_)) => {
1511+
// If the method is defined (but ambiguous) for the receiver we have, it is also
1512+
// likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
1513+
// the receiver, then it might disambiguate this method, but I think these
1514+
// suggestions are generally misleading (see #94218).
1515+
break;
1516+
}
1517+
_ => {}
15081518
}
1519+
15091520
for (rcvr_ty, pre) in &[
15101521
(self.tcx.mk_lang_item(*rcvr_ty, LangItem::OwnedBox), "Box::new"),
15111522
(self.tcx.mk_lang_item(*rcvr_ty, LangItem::Pin), "Pin::new"),

src/test/ui/rust-2021/future-prelude-collision-shadow.stderr

-26
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,8 @@ error[E0599]: no method named `try_into` found for type `u8` in the current scop
44
LL | let _: u32 = 3u8.try_into().unwrap();
55
| ^^^^^^^^ method not found in `u8`
66
|
7-
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
8-
|
9-
LL | fn try_into(self) -> Result<T, Self::Error>;
10-
| --------
11-
| |
12-
| the method is available for `Box<u8>` here
13-
| the method is available for `Pin<u8>` here
14-
| the method is available for `Arc<u8>` here
15-
| the method is available for `Rc<u8>` here
16-
|
177
= help: items from traits can only be used if the trait is in scope
188
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
19-
help: consider wrapping the receiver expression with the appropriate type
20-
|
21-
LL | let _: u32 = Box::new(3u8).try_into().unwrap();
22-
| +++++++++ +
23-
help: consider wrapping the receiver expression with the appropriate type
24-
|
25-
LL | let _: u32 = Pin::new(3u8).try_into().unwrap();
26-
| +++++++++ +
27-
help: consider wrapping the receiver expression with the appropriate type
28-
|
29-
LL | let _: u32 = Arc::new(3u8).try_into().unwrap();
30-
| +++++++++ +
31-
help: consider wrapping the receiver expression with the appropriate type
32-
|
33-
LL | let _: u32 = Rc::new(3u8).try_into().unwrap();
34-
| ++++++++ +
359
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
3610
|
3711
LL | use crate::m::TryIntoU32;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
mod banana {
2+
//~^ HELP the following traits are implemented but not in scope
3+
pub struct Chaenomeles;
4+
5+
pub trait Apple {
6+
fn pick(&self) {}
7+
}
8+
impl Apple for Chaenomeles {}
9+
10+
pub trait Peach {
11+
fn pick(&self, a: &mut ()) {}
12+
}
13+
impl<Mango: Peach> Peach for Box<Mango> {}
14+
impl Peach for Chaenomeles {}
15+
}
16+
17+
fn main() {
18+
banana::Chaenomeles.pick()
19+
//~^ ERROR no method named
20+
//~| HELP items from traits can only be used if the trait is in scope
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope
2+
--> $DIR/dont-wrap-ambiguous-receivers.rs:18:25
3+
|
4+
LL | pub struct Chaenomeles;
5+
| ----------------------- method `pick` not found for this
6+
...
7+
LL | banana::Chaenomeles.pick()
8+
| ^^^^ method not found in `Chaenomeles`
9+
|
10+
= help: items from traits can only be used if the trait is in scope
11+
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
12+
|
13+
LL | use banana::Apple;
14+
|
15+
LL | use banana::Peach;
16+
|
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)