Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest calling associated fn inside traits #78420

Merged
merged 1 commit into from
Nov 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ impl<'a> PathSource<'a> {

#[derive(Default)]
struct DiagnosticMetadata<'ast> {
/// The current trait's associated types' ident, used for diagnostic suggestions.
current_trait_assoc_types: Vec<Ident>,
/// The current trait's associated items' ident, used for diagnostic suggestions.
current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,

/// The current self type if inside an impl (used for better errors).
current_self_type: Option<Ty>,
Expand Down Expand Up @@ -1148,26 +1148,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
result
}

/// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
/// When evaluating a `trait` use its associated types' idents for suggestions in E0412.
fn with_trait_items<T>(
&mut self,
trait_items: &Vec<P<AssocItem>>,
trait_items: &'ast Vec<P<AssocItem>>,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let trait_assoc_types = replace(
&mut self.diagnostic_metadata.current_trait_assoc_types,
trait_items
.iter()
.filter_map(|item| match &item.kind {
AssocItemKind::TyAlias(_, _, bounds, _) if bounds.is_empty() => {
Some(item.ident)
}
_ => None,
})
.collect(),
let trait_assoc_items = replace(
&mut self.diagnostic_metadata.current_trait_assoc_items,
Some(&trait_items[..]),
);
let result = f(self);
self.diagnostic_metadata.current_trait_assoc_types = trait_assoc_types;
self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items;
result
}

Expand Down
58 changes: 47 additions & 11 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,21 @@ type Res = def::Res<ast::NodeId>;
enum AssocSuggestion {
Field,
MethodWithSelf,
AssocItem,
AssocFn,
AssocType,
AssocConst,
}

impl AssocSuggestion {
fn action(&self) -> &'static str {
match self {
AssocSuggestion::Field => "use the available field",
AssocSuggestion::MethodWithSelf => "call the method with the fully-qualified path",
AssocSuggestion::AssocFn => "call the associated function",
AssocSuggestion::AssocConst => "use the associated `const`",
AssocSuggestion::AssocType => "use the associated type",
}
}
}

crate enum MissingLifetimeSpot<'tcx> {
Expand Down Expand Up @@ -386,15 +400,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
AssocSuggestion::MethodWithSelf if self_is_available => {
err.span_suggestion(
span,
"try",
"you might have meant to call the method",
format!("self.{}", path_str),
Applicability::MachineApplicable,
);
}
AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
AssocSuggestion::MethodWithSelf
| AssocSuggestion::AssocFn
| AssocSuggestion::AssocConst
| AssocSuggestion::AssocType => {
err.span_suggestion(
span,
"try",
&format!("you might have meant to {}", candidate.action()),
format!("Self::{}", path_str),
Applicability::MachineApplicable,
);
Expand Down Expand Up @@ -1048,9 +1065,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}

for assoc_type_ident in &self.diagnostic_metadata.current_trait_assoc_types {
if *assoc_type_ident == ident {
return Some(AssocSuggestion::AssocItem);
if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items {
for assoc_item in &items[..] {
if assoc_item.ident == ident {
return Some(match &assoc_item.kind {
ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
ast::AssocItemKind::Fn(_, sig, ..) if sig.decl.has_self() => {
AssocSuggestion::MethodWithSelf
}
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn,
ast::AssocItemKind::TyAlias(..) => AssocSuggestion::AssocType,
ast::AssocItemKind::MacCall(_) => continue,
});
}
}
}

Expand All @@ -1066,11 +1093,20 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) {
let res = binding.res();
if filter_fn(res) {
return Some(if self.r.has_self.contains(&res.def_id()) {
AssocSuggestion::MethodWithSelf
if self.r.has_self.contains(&res.def_id()) {
return Some(AssocSuggestion::MethodWithSelf);
} else {
AssocSuggestion::AssocItem
});
match res {
Res::Def(DefKind::AssocFn, _) => return Some(AssocSuggestion::AssocFn),
Res::Def(DefKind::AssocConst, _) => {
return Some(AssocSuggestion::AssocConst);
}
Res::Def(DefKind::AssocTy, _) => {
return Some(AssocSuggestion::AssocType);
}
_ => {}
}
}
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/test/ui/resolve/associated-fn-called-as-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
struct S;
impl Foo for S {
fn parse(s:&str) {
for c in s.chars() {
match c {
'0'..='9' => collect_primary(&c), //~ ERROR cannot find function `collect_primary`
//~^ HELP you might have meant to call the associated function
'+' | '-' => println!("We got a sign: {}", c),
_ => println!("Not a number!")
}
}
}
}
trait Foo {
fn collect_primary(ch:&char) { }
fn parse(s:&str);
}
trait Bar {
fn collect_primary(ch:&char) { }
fn parse(s:&str) {
for c in s.chars() {
match c {
'0'..='9' => collect_primary(&c), //~ ERROR cannot find function `collect_primary`
//~^ HELP you might have meant to call the associated function
'+' | '-' => println!("We got a sign: {}", c),
_ => println!("Not a number!")
}
}
}
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/resolve/associated-fn-called-as-fn.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0425]: cannot find function `collect_primary` in this scope
--> $DIR/associated-fn-called-as-fn.rs:6:30
|
LL | '0'..='9' => collect_primary(&c),
| ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary`

error[E0425]: cannot find function `collect_primary` in this scope
--> $DIR/associated-fn-called-as-fn.rs:23:30
|
LL | '0'..='9' => collect_primary(&c),
| ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0425`.
30 changes: 15 additions & 15 deletions src/test/ui/resolve/issue-14254.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:19:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `a` in this scope
--> $DIR/issue-14254.rs:21:9
Expand All @@ -14,7 +14,7 @@ error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:28:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `x` in this scope
--> $DIR/issue-14254.rs:30:9
Expand All @@ -38,7 +38,7 @@ error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:36:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find value `b` in this scope
--> $DIR/issue-14254.rs:38:9
Expand All @@ -50,7 +50,7 @@ error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:45:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `x` in this scope
--> $DIR/issue-14254.rs:47:9
Expand All @@ -74,7 +74,7 @@ error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:53:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find value `b` in this scope
--> $DIR/issue-14254.rs:55:9
Expand All @@ -86,61 +86,61 @@ error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:62:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:64:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:71:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:73:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:80:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:82:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:89:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:91:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error[E0425]: cannot find function `baz` in this scope
--> $DIR/issue-14254.rs:98:9
|
LL | baz();
| ^^^ help: try: `self.baz`
| ^^^ help: you might have meant to call the method: `self.baz`

error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:100:9
|
LL | bah;
| ^^^ help: try: `Self::bah`
| ^^^ help: you might have meant to call the associated function: `Self::bah`

error: aborting due to 24 previous errors

Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/resolve/issue-2356.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ error[E0425]: cannot find function `clone` in this scope
--> $DIR/issue-2356.rs:24:5
|
LL | clone();
| ^^^^^ help: try: `self.clone`
| ^^^^^ help: you might have meant to call the method: `self.clone`

error[E0425]: cannot find function `default` in this scope
--> $DIR/issue-2356.rs:31:5
|
LL | default();
| ^^^^^^^
|
help: try
help: you might have meant to call the associated function
|
LL | Self::default();
| ^^^^^^^^^^^^^
Expand All @@ -35,7 +35,7 @@ error[E0425]: cannot find function `shave` in this scope
--> $DIR/issue-2356.rs:41:5
|
LL | shave(4);
| ^^^^^ help: try: `Self::shave`
| ^^^^^ help: you might have meant to call the associated function: `Self::shave`

error[E0425]: cannot find function `purr` in this scope
--> $DIR/issue-2356.rs:43:5
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/resolve/resolve-assoc-suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ error[E0412]: cannot find type `Type` in this scope
--> $DIR/resolve-assoc-suggestions.rs:23:16
|
LL | let _: Type;
| ^^^^ help: try: `Self::Type`
| ^^^^ help: you might have meant to use the associated type: `Self::Type`

error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope
--> $DIR/resolve-assoc-suggestions.rs:25:13
Expand Down Expand Up @@ -50,7 +50,7 @@ error[E0425]: cannot find value `method` in this scope
--> $DIR/resolve-assoc-suggestions.rs:34:9
|
LL | method;
| ^^^^^^ help: try: `self.method`
| ^^^^^^ help: you might have meant to call the method: `self.method`

error: aborting due to 9 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/resolve/resolve-speculative-adjustment.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ error[E0425]: cannot find function `method` in this scope
--> $DIR/resolve-speculative-adjustment.rs:25:9
|
LL | method();
| ^^^^^^ help: try: `self.method`
| ^^^^^^ help: you might have meant to call the method: `self.method`

error: aborting due to 4 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/suggestions/assoc-type-in-method-return.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0412]: cannot find type `Bla` in this scope
--> $DIR/assoc-type-in-method-return.rs:3:25
|
LL | fn to_bla(&self) -> Bla;
| ^^^ help: try: `Self::Bla`
| ^^^ help: you might have meant to use the associated type: `Self::Bla`

error: aborting due to previous error

Expand Down