Skip to content

Commit c8af93f

Browse files
committed
Auto merge of #38168 - estebank:help-E0034, r=nrc
E0034: provide disambiguated syntax for candidates For a given file ```rust trait A { fn foo(&self) {} } trait B : A { fn foo(&self) {} } fn bar<T: B>(a: &T) { a.foo() } ``` provide the following output ``` error[E0034]: multiple applicable items in scope --> file.rs:6:5 | 6 | a.foo(1) | ^^^ multiple `foo` found | note: candidate #1 is defined in the trait `A` --> file.rs:2:11 | 2 | trait A { fn foo(&self, a: usize) {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: to use it here write `A::foo(&a, 1)` instead --> file.rs:6:5 | 6 | a.foo(1) | ^^^ note: candidate #2 is defined in the trait `B` --> file.rs:3:15 | 3 | trait B : A { fn foo(&self, a: usize) {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: to use it here write `B::foo(&a, 1)` instead --> file.rs:6:5 | 6 | a.foo(1) | ^^^ ``` Fix #37767.
2 parents be1daa4 + f595ea2 commit c8af93f

File tree

7 files changed

+224
-8
lines changed

7 files changed

+224
-8
lines changed

src/librustc/ty/sty.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
11211121
}
11221122
}
11231123

1124+
pub fn is_mutable_pointer(&self) -> bool {
1125+
match self.sty {
1126+
TyRawPtr(tnm) | TyRef(_, tnm) => if let hir::Mutability::MutMutable = tnm.mutbl {
1127+
true
1128+
} else {
1129+
false
1130+
},
1131+
_ => false
1132+
}
1133+
}
1134+
11241135
pub fn is_unsafe_ptr(&self) -> bool {
11251136
match self.sty {
11261137
TyRawPtr(_) => return true,

src/librustc_typeck/check/method/suggest.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use errors::DiagnosticBuilder;
2727
use syntax_pos::Span;
2828

2929
use rustc::hir;
30+
use rustc::hir::print;
3031
use rustc::infer::type_variable::TypeVariableOrigin;
3132

3233
use std::cell;
@@ -71,7 +72,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7172
rcvr_ty: Ty<'tcx>,
7273
item_name: ast::Name,
7374
rcvr_expr: Option<&hir::Expr>,
74-
error: MethodError<'tcx>) {
75+
error: MethodError<'tcx>,
76+
args: Option<&'gcx [hir::Expr]>) {
7577
// avoid suggestions when we don't know what's going on.
7678
if rcvr_ty.references_error() {
7779
return;
@@ -131,6 +133,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
131133
"candidate #{} is defined in the trait `{}`",
132134
idx + 1,
133135
self.tcx.item_path_str(trait_did));
136+
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
137+
instead",
138+
self.tcx.item_path_str(trait_did),
139+
item_name,
140+
if rcvr_ty.is_region_ptr() && args.is_some() {
141+
if rcvr_ty.is_mutable_pointer() {
142+
"&mut "
143+
} else {
144+
"&"
145+
}
146+
} else {
147+
""
148+
},
149+
args.map(|arg| arg.iter()
150+
.map(|arg| print::to_string(print::NO_ANN,
151+
|s| s.print_expr(arg)))
152+
.collect::<Vec<_>>()
153+
.join(", ")).unwrap_or("...".to_owned())));
134154
}
135155
}
136156
}

src/librustc_typeck/check/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -2867,8 +2867,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
28672867
}
28682868
Err(error) => {
28692869
if method_name.node != keywords::Invalid.name() {
2870-
self.report_method_error(method_name.span, expr_t,
2871-
method_name.node, Some(rcvr), error);
2870+
self.report_method_error(method_name.span,
2871+
expr_t,
2872+
method_name.node,
2873+
Some(rcvr),
2874+
error,
2875+
Some(args));
28722876
}
28732877
self.write_error(expr.id);
28742878
self.tcx.types.err
@@ -4051,7 +4055,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40514055
_ => Def::Err,
40524056
};
40534057
if item_name != keywords::Invalid.name() {
4054-
self.report_method_error(span, ty, item_name, None, error);
4058+
self.report_method_error(span, ty, item_name, None, error, None);
40554059
}
40564060
def
40574061
}

src/test/ui/span/issue-37767.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait A {
12+
fn foo(&mut self) {}
13+
}
14+
15+
trait B : A {
16+
fn foo(&mut self) {}
17+
}
18+
19+
fn bar<T: B>(a: &T) {
20+
a.foo()
21+
}
22+
23+
trait C {
24+
fn foo(&self) {}
25+
}
26+
27+
trait D : C {
28+
fn foo(&self) {}
29+
}
30+
31+
fn quz<T: D>(a: &T) {
32+
a.foo()
33+
}
34+
35+
trait E : Sized {
36+
fn foo(self) {}
37+
}
38+
39+
trait F : E {
40+
fn foo(self) {}
41+
}
42+
43+
fn foo<T: F>(a: T) {
44+
a.foo()
45+
}
46+
47+
fn pass<T: C>(a: &T) {
48+
a.foo()
49+
}
50+
51+
fn main() {}

src/test/ui/span/issue-37767.stderr

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error[E0034]: multiple applicable items in scope
2+
--> $DIR/issue-37767.rs:20:7
3+
|
4+
20 | a.foo()
5+
| ^^^ multiple `foo` found
6+
|
7+
note: candidate #1 is defined in the trait `A`
8+
--> $DIR/issue-37767.rs:12:5
9+
|
10+
12 | fn foo(&mut self) {}
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
= help: to disambiguate the method call, write `A::foo(&a)` instead
13+
note: candidate #2 is defined in the trait `B`
14+
--> $DIR/issue-37767.rs:16:5
15+
|
16+
16 | fn foo(&mut self) {}
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
= help: to disambiguate the method call, write `B::foo(&a)` instead
19+
20+
error[E0034]: multiple applicable items in scope
21+
--> $DIR/issue-37767.rs:32:7
22+
|
23+
32 | a.foo()
24+
| ^^^ multiple `foo` found
25+
|
26+
note: candidate #1 is defined in the trait `C`
27+
--> $DIR/issue-37767.rs:24:5
28+
|
29+
24 | fn foo(&self) {}
30+
| ^^^^^^^^^^^^^^^^
31+
= help: to disambiguate the method call, write `C::foo(&a)` instead
32+
note: candidate #2 is defined in the trait `D`
33+
--> $DIR/issue-37767.rs:28:5
34+
|
35+
28 | fn foo(&self) {}
36+
| ^^^^^^^^^^^^^^^^
37+
= help: to disambiguate the method call, write `D::foo(&a)` instead
38+
39+
error[E0034]: multiple applicable items in scope
40+
--> $DIR/issue-37767.rs:44:7
41+
|
42+
44 | a.foo()
43+
| ^^^ multiple `foo` found
44+
|
45+
note: candidate #1 is defined in the trait `E`
46+
--> $DIR/issue-37767.rs:36:5
47+
|
48+
36 | fn foo(self) {}
49+
| ^^^^^^^^^^^^^^^
50+
= help: to disambiguate the method call, write `E::foo(a)` instead
51+
note: candidate #2 is defined in the trait `F`
52+
--> $DIR/issue-37767.rs:40:5
53+
|
54+
40 | fn foo(self) {}
55+
| ^^^^^^^^^^^^^^^
56+
= help: to disambiguate the method call, write `F::foo(a)` instead
57+
58+
error: aborting due to 3 previous errors
59+

src/test/compile-fail/issue-7575.rs src/test/ui/span/issue-7575.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,19 @@ impl ManyImplTrait for Myisize {}
7373
fn no_param_bound(u: usize, m: Myisize) -> usize {
7474
u.f8(42) + u.f9(342) + m.fff(42)
7575
//~^ ERROR no method named `f9` found for type `usize` in the current scope
76-
//~^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
77-
//~^^^ ERROR no method named `fff` found for type `Myisize` in the current scope
78-
//~^^^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
76+
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
77+
//~| NOTE to use it here write `CtxtFn::f9(u, 342)` instead
78+
//~| ERROR no method named `fff` found for type `Myisize` in the current scope
79+
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
80+
//~| NOTE to use it here write `OtherTrait::f9(u, 342)` instead
81+
//~| NOTE to use it here write `UnusedTrait::f9(u, 342)` instead
7982
}
8083

8184
fn param_bound<T: ManyImplTrait>(t: T) -> bool {
8285
t.is_str()
8386
//~^ ERROR no method named `is_str` found for type `T` in the current scope
84-
//~^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
87+
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
88+
//~| NOTE to use it here write `ManyImplTrait::is_str(t)` instead
8589
}
8690

8791
fn main() {

src/test/ui/span/issue-7575.stderr

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error: no method named `f9` found for type `usize` in the current scope
2+
--> $DIR/issue-7575.rs:74:18
3+
|
4+
74 | u.f8(42) + u.f9(342) + m.fff(42)
5+
| ^^
6+
|
7+
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
8+
note: candidate #1 is defined in the trait `CtxtFn`
9+
--> $DIR/issue-7575.rs:16:5
10+
|
11+
16 | fn f9(usize) -> usize; //~ NOTE candidate
12+
| ^^^^^^^^^^^^^^^^^^^^^^
13+
= help: to disambiguate the method call, write `CtxtFn::f9(u, 342)` instead
14+
note: candidate #2 is defined in the trait `OtherTrait`
15+
--> $DIR/issue-7575.rs:20:5
16+
|
17+
20 | fn f9(usize) -> usize; //~ NOTE candidate
18+
| ^^^^^^^^^^^^^^^^^^^^^^
19+
= help: to disambiguate the method call, write `OtherTrait::f9(u, 342)` instead
20+
note: candidate #3 is defined in the trait `UnusedTrait`
21+
--> $DIR/issue-7575.rs:29:5
22+
|
23+
29 | fn f9(usize) -> usize; //~ NOTE candidate
24+
| ^^^^^^^^^^^^^^^^^^^^^^
25+
= help: to disambiguate the method call, write `UnusedTrait::f9(u, 342)` instead
26+
= help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item `f9`, perhaps you need to implement one of them:
27+
= help: candidate #1: `CtxtFn`
28+
= help: candidate #2: `OtherTrait`
29+
= help: candidate #3: `UnusedTrait`
30+
31+
error: no method named `fff` found for type `Myisize` in the current scope
32+
--> $DIR/issue-7575.rs:74:30
33+
|
34+
74 | u.f8(42) + u.f9(342) + m.fff(42)
35+
| ^^^
36+
|
37+
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
38+
note: candidate #1 is defined in an impl for the type `Myisize`
39+
--> $DIR/issue-7575.rs:51:5
40+
|
41+
51 | fn fff(i: isize) -> isize { //~ NOTE candidate
42+
| _____^ starting here...
43+
52 | | i
44+
53 | | }
45+
| |_____^ ...ending here
46+
47+
error: no method named `is_str` found for type `T` in the current scope
48+
--> $DIR/issue-7575.rs:85:7
49+
|
50+
85 | t.is_str()
51+
| ^^^^^^
52+
|
53+
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
54+
note: candidate #1 is defined in the trait `ManyImplTrait`
55+
--> $DIR/issue-7575.rs:57:5
56+
|
57+
57 | fn is_str() -> bool { //~ NOTE candidate
58+
| _____^ starting here...
59+
58 | | false
60+
59 | | }
61+
| |_____^ ...ending here
62+
= help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead
63+
= help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `is_str`, perhaps you need to implement it:
64+
= help: candidate #1: `ManyImplTrait`
65+
66+
error: aborting due to 3 previous errors
67+

0 commit comments

Comments
 (0)