/// Maybe there was a typo where a comma was forgotten before
/// FRU syntax
MaybeFruTypo,
+ CallAssocMethod,
}
fn default_track_diagnostic(_: &Diagnostic) {}
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
let ty = match res {
Res::Err => {
+ self.suggest_assoc_method_call(segs);
let e =
self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
use crate::FnCtxt;
use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::StashKey;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
MultiSpan,
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
+use rustc_hir::PatKind::Binding;
+use rustc_hir::PathSegment;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::{
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
};
-use std::cmp::Ordering;
-use std::iter;
-
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
+use rustc_hir::intravisit::Visitor;
+use std::cmp::Ordering;
+use std::iter;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
false
}
+ /// For code `rect::area(...)`,
+ /// if `rect` is a local variable and `area` is a valid assoc method for it,
+ /// we try to suggest `rect.area()`
+ pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
+ debug!("suggest_assoc_method_call segs: {:?}", segs);
+ let [seg1, seg2] = segs else { return; };
+ let Some(mut diag) =
+ self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
+ else { return };
+
+ let map = self.infcx.tcx.hir();
+ let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
+ struct LetVisitor<'a> {
+ result: Option<&'a hir::Expr<'a>>,
+ ident_name: Symbol,
+ }
+
+ impl<'v> Visitor<'v> for LetVisitor<'v> {
+ fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+ if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind {
+ if let Binding(_, _, ident, ..) = pat.kind &&
+ ident.name == self.ident_name {
+ self.result = *init;
+ }
+ }
+ hir::intravisit::walk_stmt(self, ex);
+ }
+ }
+
+ let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
+ visitor.visit_body(&body);
+
+ let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
+ if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
+ let Some(expr) = visitor.result {
+ let self_ty = self.node_ty(expr.hir_id);
+ let probe = self.lookup_probe(
+ seg2.ident,
+ self_ty,
+ call_expr,
+ ProbeScope::TraitsInScope,
+ );
+ if probe.is_ok() {
+ let sm = self.infcx.tcx.sess.source_map();
+ diag.span_suggestion_verbose(
+ sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
+ "you may have meant to call an instance method",
+ ".".to_string(),
+ Applicability::MaybeIncorrect
+ );
+ }
+ }
+ diag.emit();
+ }
+
/// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
fn suggest_calling_method_on_field(
&self,
(format!("use of undeclared type `{}`", ident), suggestion)
} else {
- let suggestion = if ident.name == sym::alloc {
- Some((
+ let mut suggestion = None;
+ if ident.name == sym::alloc {
+ suggestion = Some((
vec![],
String::from("add `extern crate alloc` to use the `alloc` crate"),
Applicability::MaybeIncorrect,
))
- } else {
+ }
+
+ suggestion = suggestion.or_else(|| {
self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
|sugg| {
(
)
},
)
- };
+ });
(format!("use of undeclared crate or module `{}`", ident), suggestion)
}
}
// Before we start looking for candidates, we have to get our hands
// on the type user is trying to perform invocation on; basically:
// we're transforming `HashMap::new` into just `HashMap`.
- let path = match path.split_last() {
+ let prefix_path = match path.split_last() {
Some((_, path)) if !path.is_empty() => path,
_ => return Some(parent_err),
};
let (mut err, candidates) =
- this.smart_resolve_report_errors(path, path_span, PathSource::Type, None);
+ this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None);
// There are two different error messages user might receive at
// this point:
if this.should_report_errs() {
if candidates.is_empty() {
- // When there is no suggested imports, we can just emit the error
- // and suggestions immediately. Note that we bypass the usually error
- // reporting routine (ie via `self.r.report_error`) because we need
- // to post-process the `ResolutionError` above.
- err.emit();
+ if path.len() == 2 && prefix_path.len() == 1 {
+ // Delay to check whether methond name is an associated function or not
+ // ```
+ // let foo = Foo {};
+ // foo::bar(); // possibly suggest to foo.bar();
+ //```
+ err.stash(
+ prefix_path[0].ident.span,
+ rustc_errors::StashKey::CallAssocMethod,
+ );
+ } else {
+ // When there is no suggested imports, we can just emit the error
+ // and suggestions immediately. Note that we bypass the usually error
+ // reporting routine (ie via `self.r.report_error`) because we need
+ // to post-process the `ResolutionError` above.
+ err.emit();
+ }
} else {
// If there are suggested imports, the error reporting is delayed
this.r.use_injections.push(UseError {
def_id,
instead: false,
suggestion: None,
- path: path.into(),
+ path: prefix_path.into(),
is_call: source.is_call(),
});
}
-error[E0433]: failed to resolve: use of undeclared crate or module `thing`
- --> $DIR/bad-module.rs:2:15
- |
-LL | let foo = thing::len(Vec::new());
- | ^^^^^ use of undeclared crate or module `thing`
-
error[E0433]: failed to resolve: use of undeclared crate or module `foo`
--> $DIR/bad-module.rs:5:15
|
LL | let foo = foo::bar::baz();
| ^^^ use of undeclared crate or module `foo`
+error[E0433]: failed to resolve: use of undeclared crate or module `thing`
+ --> $DIR/bad-module.rs:2:15
+ |
+LL | let foo = thing::len(Vec::new());
+ | ^^^^^ use of undeclared crate or module `thing`
+
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0433`.
--- /dev/null
+struct Rectangle {
+ width: i32,
+ height: i32,
+}
+impl Rectangle {
+ fn new(width: i32, height: i32) -> Self {
+ Self { width, height }
+ }
+}
+
+fn main() {
+ let rect = Rectangle::new(3, 4);
+ // `area` is not implemented for `Rectangle`, so this should not suggest
+ let _ = rect::area();
+ //~^ ERROR failed to resolve: use of undeclared crate or module `rect`
+}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared crate or module `rect`
+ --> $DIR/issue-101749-2.rs:14:13
+ |
+LL | let _ = rect::area();
+ | ^^^^ use of undeclared crate or module `rect`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
--- /dev/null
+// run-rustfix
+struct Rectangle {
+ width: i32,
+ height: i32,
+}
+impl Rectangle {
+ fn new(width: i32, height: i32) -> Self {
+ Self { width, height }
+ }
+ fn area(&self) -> i32 {
+ self.height * self.width
+ }
+}
+
+fn main() {
+ let rect = Rectangle::new(3, 4);
+ let _ = rect.area();
+ //~^ ERROR failed to resolve: use of undeclared crate or module `rect`
+}
--- /dev/null
+// run-rustfix
+struct Rectangle {
+ width: i32,
+ height: i32,
+}
+impl Rectangle {
+ fn new(width: i32, height: i32) -> Self {
+ Self { width, height }
+ }
+ fn area(&self) -> i32 {
+ self.height * self.width
+ }
+}
+
+fn main() {
+ let rect = Rectangle::new(3, 4);
+ let _ = rect::area();
+ //~^ ERROR failed to resolve: use of undeclared crate or module `rect`
+}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared crate or module `rect`
+ --> $DIR/issue-101749.rs:17:13
+ |
+LL | let _ = rect::area();
+ | ^^^^ use of undeclared crate or module `rect`
+ |
+help: you may have meant to call an instance method
+ |
+LL | let _ = rect.area();
+ | ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
-error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions
- --> $DIR/issue-24968.rs:21:19
- |
-LL | const FOO2: u32 = Self::bar();
- | ^^^^ `Self` is only available in impls, traits, and type definitions
-
-error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions
- --> $DIR/issue-24968.rs:27:22
- |
-LL | static FOO_S2: u32 = Self::bar();
- | ^^^^ `Self` is only available in impls, traits, and type definitions
-
error[E0411]: cannot find type `Self` in this scope
--> $DIR/issue-24968.rs:3:11
|
| |
| `Self` not allowed in a static item
+error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions
+ --> $DIR/issue-24968.rs:21:19
+ |
+LL | const FOO2: u32 = Self::bar();
+ | ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions
+ --> $DIR/issue-24968.rs:27:22
+ |
+LL | static FOO_S2: u32 = Self::bar();
+ | ^^^^ `Self` is only available in impls, traits, and type definitions
+
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0411, E0433.
+error[E0433]: failed to resolve: could not find `Struc` in `module`
+ --> $DIR/typo-suggestion-mistyped-in-path.rs:35:13
+ |
+LL | module::Struc::foo();
+ | ^^^^^
+ | |
+ | could not find `Struc` in `module`
+ | help: a struct with a similar name exists: `Struct`
+
+error[E0599]: no function or associated item named `fob` found for struct `Struct` in the current scope
+ --> $DIR/typo-suggestion-mistyped-in-path.rs:23:13
+ |
+LL | struct Struct;
+ | ------------- function or associated item `fob` not found for this struct
+...
+LL | Struct::fob();
+ | ^^^
+ | |
+ | function or associated item not found in `Struct`
+ | help: there is an associated function with a similar name: `foo`
+
error[E0433]: failed to resolve: use of undeclared type `Struc`
--> $DIR/typo-suggestion-mistyped-in-path.rs:27:5
|
LL | module::foo();
| ~~~~~~
-error[E0433]: failed to resolve: could not find `Struc` in `module`
- --> $DIR/typo-suggestion-mistyped-in-path.rs:35:13
- |
-LL | module::Struc::foo();
- | ^^^^^
- | |
- | could not find `Struc` in `module`
- | help: a struct with a similar name exists: `Struct`
-
error[E0433]: failed to resolve: use of undeclared type `Trai`
--> $DIR/typo-suggestion-mistyped-in-path.rs:39:5
|
| use of undeclared type `Trai`
| help: a trait with a similar name exists: `Trait`
-error[E0599]: no function or associated item named `fob` found for struct `Struct` in the current scope
- --> $DIR/typo-suggestion-mistyped-in-path.rs:23:13
- |
-LL | struct Struct;
- | ------------- function or associated item `fob` not found for this struct
-...
-LL | Struct::fob();
- | ^^^
- | |
- | function or associated item not found in `Struct`
- | help: there is an associated function with a similar name: `foo`
-
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0433, E0599.
-error[E0433]: failed to resolve: use of undeclared type `GooMap`
- --> $DIR/use_suggestion.rs:3:14
- |
-LL | let x2 = GooMap::new();
- | ^^^^^^ use of undeclared type `GooMap`
-
error[E0433]: failed to resolve: use of undeclared type `HashMap`
--> $DIR/use_suggestion.rs:2:14
|
LL | let y2: GooMap;
| ^^^^^^ not found in this scope
+error[E0433]: failed to resolve: use of undeclared type `GooMap`
+ --> $DIR/use_suggestion.rs:3:14
+ |
+LL | let x2 = GooMap::new();
+ | ^^^^^^ use of undeclared type `GooMap`
+
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0412, E0433.
LL | use bar::bar;
| ~~~
-error[E0433]: failed to resolve: use of undeclared crate or module `bar`
- --> $DIR/crate-or-module-typo.rs:6:20
- |
-LL | pub fn bar() { bar::baz(); }
- | ^^^ use of undeclared crate or module `bar`
-
error[E0433]: failed to resolve: use of undeclared crate or module `st`
--> $DIR/crate-or-module-typo.rs:14:10
|
LL | bar: std::cell::Cell<bool>
| ~~~
+error[E0433]: failed to resolve: use of undeclared crate or module `bar`
+ --> $DIR/crate-or-module-typo.rs:6:20
+ |
+LL | pub fn bar() { bar::baz(); }
+ | ^^^ use of undeclared crate or module `bar`
+
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0432, E0433.