Skip to content

Commit c30c8ac

Browse files
authored
Rollup merge of rust-lang#62921 - iluuu1994:improve-help-for-method-disambiguation, r=estebank
Add method disambiguation help for trait implementation Closes rust-lang#51046 Closes rust-lang#40471
2 parents 8bc8562 + be510db commit c30c8ac

13 files changed

+123
-19
lines changed

src/librustc_typeck/check/method/suggest.rs

+31-19
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use rustc::hir::{self, ExprKind, Node, QPath};
1010
use rustc::hir::def::{Res, DefKind};
1111
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
1212
use rustc::hir::map as hir_map;
13-
use rustc::hir::print;
1413
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1514
use rustc::traits::Obligation;
1615
use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
@@ -78,6 +77,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7877
return;
7978
}
8079

80+
let print_disambiguation_help = |
81+
err: &mut DiagnosticBuilder<'_>,
82+
trait_name: String,
83+
| {
84+
err.help(&format!(
85+
"to disambiguate the method call, write `{}::{}({}{})` instead",
86+
trait_name,
87+
item_name,
88+
if rcvr_ty.is_region_ptr() && args.is_some() {
89+
if rcvr_ty.is_mutable_pointer() {
90+
"&mut "
91+
} else {
92+
"&"
93+
}
94+
} else {
95+
""
96+
},
97+
args.map(|arg| arg
98+
.iter()
99+
.map(|arg| self.tcx.sess.source_map().span_to_snippet(arg.span)
100+
.unwrap_or_else(|_| "...".to_owned()))
101+
.collect::<Vec<_>>()
102+
.join(", ")
103+
).unwrap_or_else(|| "...".to_owned())
104+
));
105+
};
106+
81107
let report_candidates = |
82108
span: Span,
83109
err: &mut DiagnosticBuilder<'_>,
@@ -139,6 +165,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
139165
} else {
140166
err.note(&note_str);
141167
}
168+
if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
169+
print_disambiguation_help(err, self.tcx.def_path_str(trait_ref.def_id));
170+
}
142171
}
143172
CandidateSource::TraitSource(trait_did) => {
144173
let item = match self.associated_item(
@@ -163,24 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163192
"the candidate is defined in the trait `{}`",
164193
self.tcx.def_path_str(trait_did));
165194
}
166-
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
167-
instead",
168-
self.tcx.def_path_str(trait_did),
169-
item_name,
170-
if rcvr_ty.is_region_ptr() && args.is_some() {
171-
if rcvr_ty.is_mutable_pointer() {
172-
"&mut "
173-
} else {
174-
"&"
175-
}
176-
} else {
177-
""
178-
},
179-
args.map(|arg| arg.iter()
180-
.map(|arg| print::to_string(print::NO_ANN,
181-
|s| s.print_expr(arg)))
182-
.collect::<Vec<_>>()
183-
.join(", ")).unwrap_or_else(|| "...".to_owned())));
195+
print_disambiguation_help(err, self.tcx.def_path_str(trait_did));
184196
}
185197
}
186198
}

src/test/ui/associated-const/associated-const-ambiguity-report.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32`
99
|
1010
LL | const ID: i32 = 1;
1111
| ^^^^^^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `Foo::ID(...)` instead
1213
note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32`
1314
--> $DIR/associated-const-ambiguity-report.rs:14:5
1415
|
1516
LL | const ID: i32 = 3;
1617
| ^^^^^^^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `Bar::ID(...)` instead
1719

1820
error: aborting due to previous error
1921

src/test/ui/error-codes/E0034.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Tes
99
|
1010
LL | fn foo() {}
1111
| ^^^^^^^^
12+
= help: to disambiguate the method call, write `Trait1::foo(...)` instead
1213
note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test`
1314
--> $DIR/E0034.rs:16:5
1415
|
1516
LL | fn foo() {}
1617
| ^^^^^^^^
18+
= help: to disambiguate the method call, write `Trait2::foo(...)` instead
1719

1820
error: aborting due to previous error
1921

src/test/ui/inference/inference_unstable_featured.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ LL | assert_eq!('x'.ipu_flatten(), 0);
55
| ^^^^^^^^^^^ multiple `ipu_flatten` found
66
|
77
= note: candidate #1 is defined in an impl of the trait `inference_unstable_iterator::IpuIterator` for the type `char`
8+
= help: to disambiguate the method call, write `inference_unstable_iterator::IpuIterator::ipu_flatten('x')` instead
89
= note: candidate #2 is defined in an impl of the trait `inference_unstable_itertools::IpuItertools` for the type `char`
10+
= help: to disambiguate the method call, write `inference_unstable_itertools::IpuItertools::ipu_flatten('x')` instead
911

1012
error: aborting due to previous error
1113

src/test/ui/issues/issue-3702-2.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type
99
|
1010
LL | fn to_int(&self) -> isize { 0 }
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `ToPrimitive::to_int(&self)` instead
1213
note: candidate #2 is defined in an impl of the trait `Add` for the type `isize`
1314
--> $DIR/issue-3702-2.rs:14:5
1415
|
1516
LL | fn to_int(&self) -> isize { *self }
1617
| ^^^^^^^^^^^^^^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `Add::to_int(&self)` instead
1719

1820
error: aborting due to previous error
1921

src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ note: candidate #1 is defined in an impl of the trait `Me2` for the type `usize`
99
|
1010
LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
1111
| ^^^^^^^^^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `Me2::me(1_usize)` instead
1213
= note: candidate #2 is defined in an impl of the trait `ambig_impl_2_lib::Me` for the type `usize`
14+
= help: to disambiguate the method call, write `ambig_impl_2_lib::Me::me(1_usize)` instead
1315

1416
error: aborting due to previous error
1517

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait A { fn foo(self); }
2+
trait B { fn foo(self); }
3+
4+
struct AB {}
5+
6+
impl A for AB {
7+
fn foo(self) {}
8+
}
9+
10+
impl B for AB {
11+
fn foo(self) {}
12+
}
13+
14+
fn main() {
15+
AB {}.foo(); //~ ERROR E0034
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/method-ambig-two-traits-from-impls.rs:15:11
3+
|
4+
LL | AB {}.foo();
5+
| ^^^ multiple `foo` found
6+
|
7+
note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
8+
--> $DIR/method-ambig-two-traits-from-impls.rs:7:5
9+
|
10+
LL | fn foo(self) {}
11+
| ^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `A::foo(AB {})` instead
13+
note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
14+
--> $DIR/method-ambig-two-traits-from-impls.rs:11:5
15+
|
16+
LL | fn foo(self) {}
17+
| ^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `B::foo(AB {})` instead
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0034`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait A { fn foo(); }
2+
trait B { fn foo(); }
3+
4+
struct AB {}
5+
6+
impl A for AB {
7+
fn foo() {}
8+
}
9+
10+
impl B for AB {
11+
fn foo() {}
12+
}
13+
14+
fn main() {
15+
AB::foo(); //~ ERROR E0034
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/method-ambig-two-traits-from-impls2.rs:15:5
3+
|
4+
LL | AB::foo();
5+
| ^^^^^^^ multiple `foo` found
6+
|
7+
note: candidate #1 is defined in an impl of the trait `A` for the type `AB`
8+
--> $DIR/method-ambig-two-traits-from-impls2.rs:7:5
9+
|
10+
LL | fn foo() {}
11+
| ^^^^^^^^
12+
= help: to disambiguate the method call, write `A::foo(...)` instead
13+
note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
14+
--> $DIR/method-ambig-two-traits-from-impls2.rs:11:5
15+
|
16+
LL | fn foo() {}
17+
| ^^^^^^^^
18+
= help: to disambiguate the method call, write `B::foo(...)` instead
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0034`.

src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize`
99
|
1010
LL | trait Foo { fn method(&self) {} }
1111
| ^^^^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `Foo::method(1_usize)` instead
1213
note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
1314
--> $DIR/method-ambig-two-traits-with-default-method.rs:6:13
1415
|
1516
LL | trait Bar { fn method(&self) {} }
1617
| ^^^^^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `Bar::method(1_usize)` instead
1719

1820
error: aborting due to previous error
1921

src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ note: candidate #1 is defined in an impl of the trait `internal::X` for the type
2727
|
2828
LL | fn foo(self: Smaht<Self, u64>) -> u64 {
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
= help: to disambiguate the method call, write `internal::X::foo(x)` instead
3031
note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_`
3132
--> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9
3233
|
3334
LL | fn foo(self) {}
3435
| ^^^^^^^^^^^^
36+
= help: to disambiguate the method call, write `nuisance_foo::NuisanceFoo::foo(x)` instead
3537
note: candidate #3 is defined in the trait `FinalFoo`
3638
--> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5
3739
|

src/test/ui/traits/trait-alias-ambiguous.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u
99
|
1010
LL | fn foo(&self) {}
1111
| ^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `inner::A::foo(t)` instead
1213
note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8`
1314
--> $DIR/trait-alias-ambiguous.rs:11:9
1415
|
1516
LL | fn foo(&self) {}
1617
| ^^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `inner::B::foo(t)` instead
1719

1820
error: aborting due to previous error
1921

0 commit comments

Comments
 (0)