diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-10-26 16:28:56 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-10-26 16:31:11 -0700 |
| commit | 9e16213610f606de0e44ac2b26ab9666bf0e83bf (patch) | |
| tree | 2e97213beb4edc887d4d325a94f66bb3cff28375 /compiler/rustc_resolve/src/late | |
| parent | 9f6c670c4b4273b2c7c0af07a524d4240c926bfc (diff) | |
| download | rust-9e16213610f606de0e44ac2b26ab9666bf0e83bf.tar.gz rust-9e16213610f606de0e44ac2b26ab9666bf0e83bf.zip | |
Suggest calling associated `fn` inside `trait`s
When calling a function that doesn't exist inside of a trait's associated `fn`, and another associated `fn` in that trait has that name, suggest calling it with the appropriate fully-qualified path. Expand the label to be more descriptive. Prompted by the following user experience: https://users.rust-lang.org/t/cannot-find-function/50663
Diffstat (limited to 'compiler/rustc_resolve/src/late')
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c24b383f3b8..75dc54e4d65 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -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> { @@ -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, ); @@ -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, + }); + } } } @@ -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); + } + _ => {} + } + } } } } |
