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.
This commit is contained in:
commit
c8af93f090
@ -1121,6 +1121,17 @@ pub fn is_region_ptr(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mutable_pointer(&self) -> bool {
|
||||
match self.sty {
|
||||
TyRawPtr(tnm) | TyRef(_, tnm) => if let hir::Mutability::MutMutable = tnm.mutbl {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_unsafe_ptr(&self) -> bool {
|
||||
match self.sty {
|
||||
TyRawPtr(_) => return true,
|
||||
|
@ -27,6 +27,7 @@
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::print;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
|
||||
use std::cell;
|
||||
@ -71,7 +72,8 @@ pub fn report_method_error(&self,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: ast::Name,
|
||||
rcvr_expr: Option<&hir::Expr>,
|
||||
error: MethodError<'tcx>) {
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'gcx [hir::Expr]>) {
|
||||
// avoid suggestions when we don't know what's going on.
|
||||
if rcvr_ty.references_error() {
|
||||
return;
|
||||
@ -131,6 +133,24 @@ pub fn report_method_error(&self,
|
||||
"candidate #{} is defined in the trait `{}`",
|
||||
idx + 1,
|
||||
self.tcx.item_path_str(trait_did));
|
||||
err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \
|
||||
instead",
|
||||
self.tcx.item_path_str(trait_did),
|
||||
item_name,
|
||||
if rcvr_ty.is_region_ptr() && args.is_some() {
|
||||
if rcvr_ty.is_mutable_pointer() {
|
||||
"&mut "
|
||||
} else {
|
||||
"&"
|
||||
}
|
||||
} else {
|
||||
""
|
||||
},
|
||||
args.map(|arg| arg.iter()
|
||||
.map(|arg| print::to_string(print::NO_ANN,
|
||||
|s| s.print_expr(arg)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")).unwrap_or("...".to_owned())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2867,8 +2867,12 @@ fn check_method_call(&self,
|
||||
}
|
||||
Err(error) => {
|
||||
if method_name.node != keywords::Invalid.name() {
|
||||
self.report_method_error(method_name.span, expr_t,
|
||||
method_name.node, Some(rcvr), error);
|
||||
self.report_method_error(method_name.span,
|
||||
expr_t,
|
||||
method_name.node,
|
||||
Some(rcvr),
|
||||
error,
|
||||
Some(args));
|
||||
}
|
||||
self.write_error(expr.id);
|
||||
self.tcx.types.err
|
||||
@ -4051,7 +4055,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
|
||||
_ => Def::Err,
|
||||
};
|
||||
if item_name != keywords::Invalid.name() {
|
||||
self.report_method_error(span, ty, item_name, None, error);
|
||||
self.report_method_error(span, ty, item_name, None, error, None);
|
||||
}
|
||||
def
|
||||
}
|
||||
|
51
src/test/ui/span/issue-37767.rs
Normal file
51
src/test/ui/span/issue-37767.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait A {
|
||||
fn foo(&mut self) {}
|
||||
}
|
||||
|
||||
trait B : A {
|
||||
fn foo(&mut self) {}
|
||||
}
|
||||
|
||||
fn bar<T: B>(a: &T) {
|
||||
a.foo()
|
||||
}
|
||||
|
||||
trait C {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
trait D : C {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
fn quz<T: D>(a: &T) {
|
||||
a.foo()
|
||||
}
|
||||
|
||||
trait E : Sized {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
trait F : E {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
fn foo<T: F>(a: T) {
|
||||
a.foo()
|
||||
}
|
||||
|
||||
fn pass<T: C>(a: &T) {
|
||||
a.foo()
|
||||
}
|
||||
|
||||
fn main() {}
|
59
src/test/ui/span/issue-37767.stderr
Normal file
59
src/test/ui/span/issue-37767.stderr
Normal file
@ -0,0 +1,59 @@
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/issue-37767.rs:20:7
|
||||
|
|
||||
20 | a.foo()
|
||||
| ^^^ multiple `foo` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `A`
|
||||
--> $DIR/issue-37767.rs:12:5
|
||||
|
|
||||
12 | fn foo(&mut self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `A::foo(&a)` instead
|
||||
note: candidate #2 is defined in the trait `B`
|
||||
--> $DIR/issue-37767.rs:16:5
|
||||
|
|
||||
16 | fn foo(&mut self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `B::foo(&a)` instead
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/issue-37767.rs:32:7
|
||||
|
|
||||
32 | a.foo()
|
||||
| ^^^ multiple `foo` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `C`
|
||||
--> $DIR/issue-37767.rs:24:5
|
||||
|
|
||||
24 | fn foo(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `C::foo(&a)` instead
|
||||
note: candidate #2 is defined in the trait `D`
|
||||
--> $DIR/issue-37767.rs:28:5
|
||||
|
|
||||
28 | fn foo(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `D::foo(&a)` instead
|
||||
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/issue-37767.rs:44:7
|
||||
|
|
||||
44 | a.foo()
|
||||
| ^^^ multiple `foo` found
|
||||
|
|
||||
note: candidate #1 is defined in the trait `E`
|
||||
--> $DIR/issue-37767.rs:36:5
|
||||
|
|
||||
36 | fn foo(self) {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `E::foo(a)` instead
|
||||
note: candidate #2 is defined in the trait `F`
|
||||
--> $DIR/issue-37767.rs:40:5
|
||||
|
|
||||
40 | fn foo(self) {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `F::foo(a)` instead
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -73,15 +73,19 @@ impl ManyImplTrait for Myisize {}
|
||||
fn no_param_bound(u: usize, m: Myisize) -> usize {
|
||||
u.f8(42) + u.f9(342) + m.fff(42)
|
||||
//~^ ERROR no method named `f9` found for type `usize` in the current scope
|
||||
//~^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~^^^ ERROR no method named `fff` found for type `Myisize` in the current scope
|
||||
//~^^^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~| NOTE to use it here write `CtxtFn::f9(u, 342)` instead
|
||||
//~| ERROR no method named `fff` found for type `Myisize` in the current scope
|
||||
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~| NOTE to use it here write `OtherTrait::f9(u, 342)` instead
|
||||
//~| NOTE to use it here write `UnusedTrait::f9(u, 342)` instead
|
||||
}
|
||||
|
||||
fn param_bound<T: ManyImplTrait>(t: T) -> bool {
|
||||
t.is_str()
|
||||
//~^ ERROR no method named `is_str` found for type `T` in the current scope
|
||||
//~^^ NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~| NOTE found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
//~| NOTE to use it here write `ManyImplTrait::is_str(t)` instead
|
||||
}
|
||||
|
||||
fn main() {
|
67
src/test/ui/span/issue-7575.stderr
Normal file
67
src/test/ui/span/issue-7575.stderr
Normal file
@ -0,0 +1,67 @@
|
||||
error: no method named `f9` found for type `usize` in the current scope
|
||||
--> $DIR/issue-7575.rs:74:18
|
||||
|
|
||||
74 | u.f8(42) + u.f9(342) + m.fff(42)
|
||||
| ^^
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: candidate #1 is defined in the trait `CtxtFn`
|
||||
--> $DIR/issue-7575.rs:16:5
|
||||
|
|
||||
16 | fn f9(usize) -> usize; //~ NOTE candidate
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `CtxtFn::f9(u, 342)` instead
|
||||
note: candidate #2 is defined in the trait `OtherTrait`
|
||||
--> $DIR/issue-7575.rs:20:5
|
||||
|
|
||||
20 | fn f9(usize) -> usize; //~ NOTE candidate
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `OtherTrait::f9(u, 342)` instead
|
||||
note: candidate #3 is defined in the trait `UnusedTrait`
|
||||
--> $DIR/issue-7575.rs:29:5
|
||||
|
|
||||
29 | fn f9(usize) -> usize; //~ NOTE candidate
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to disambiguate the method call, write `UnusedTrait::f9(u, 342)` instead
|
||||
= 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:
|
||||
= help: candidate #1: `CtxtFn`
|
||||
= help: candidate #2: `OtherTrait`
|
||||
= help: candidate #3: `UnusedTrait`
|
||||
|
||||
error: no method named `fff` found for type `Myisize` in the current scope
|
||||
--> $DIR/issue-7575.rs:74:30
|
||||
|
|
||||
74 | u.f8(42) + u.f9(342) + m.fff(42)
|
||||
| ^^^
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: candidate #1 is defined in an impl for the type `Myisize`
|
||||
--> $DIR/issue-7575.rs:51:5
|
||||
|
|
||||
51 | fn fff(i: isize) -> isize { //~ NOTE candidate
|
||||
| _____^ starting here...
|
||||
52 | | i
|
||||
53 | | }
|
||||
| |_____^ ...ending here
|
||||
|
||||
error: no method named `is_str` found for type `T` in the current scope
|
||||
--> $DIR/issue-7575.rs:85:7
|
||||
|
|
||||
85 | t.is_str()
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
|
||||
note: candidate #1 is defined in the trait `ManyImplTrait`
|
||||
--> $DIR/issue-7575.rs:57:5
|
||||
|
|
||||
57 | fn is_str() -> bool { //~ NOTE candidate
|
||||
| _____^ starting here...
|
||||
58 | | false
|
||||
59 | | }
|
||||
| |_____^ ...ending here
|
||||
= help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead
|
||||
= 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:
|
||||
= help: candidate #1: `ManyImplTrait`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user