summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/late')
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs187
1 files changed, 111 insertions, 76 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index bc5f8a37b..fd5d6fabf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -229,8 +229,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
i.ident.name == item_str.name
// Don't suggest if the item is in Fn signature arguments (#112590).
&& !sig.span.contains(item_span)
- })
- {
+ }) {
let sp = item_span.shrink_to_lo();
// Account for `Foo { field }` when suggesting `self.field` so we result on
@@ -241,7 +240,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
_ => None,
};
- let pre = if let Some(field) = field && field.is_shorthand {
+ let pre = if let Some(field) = field
+ && field.is_shorthand
+ {
format!("{item_ident}: ")
} else {
String::new()
@@ -254,13 +255,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
_ => matches!(
source,
- PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), ..})),
+ PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), .. })),
),
};
match &item.kind {
AssocItemKind::Fn(fn_)
- if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() => {
+ if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() =>
+ {
// Ensure that we only suggest `self.` if `self` is available,
// you can't call `fn foo(&self)` from `fn bar()` (#115992).
// We also want to mention that the method exists.
@@ -270,19 +272,16 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
));
None
}
- AssocItemKind::Fn(fn_)
- if !fn_.sig.decl.has_self() && !is_call => {
+ AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
span_label = Some((
item.ident.span,
"an associated function by that name is available on `Self` here",
));
None
}
- AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some((
- sp,
- "consider using the method on `Self`",
- format!("{pre}self."),
- )),
+ AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => {
+ Some((sp, "consider using the method on `Self`", format!("{pre}self.")))
+ }
AssocItemKind::Fn(_) => Some((
sp,
"consider using the associated function on `Self`",
@@ -293,7 +292,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
"consider using the associated constant on `Self`",
format!("{pre}Self::"),
)),
- _ => None
+ _ => None,
}
} else {
None
@@ -379,8 +378,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
prefix_path: &[Segment],
following_seg: Option<&Segment>,
) -> Vec<ImportSuggestion> {
- if let Some(segment) = prefix_path.last() &&
- let Some(following_seg) = following_seg
+ if let Some(segment) = prefix_path.last()
+ && let Some(following_seg) = following_seg
{
let candidates = self.r.lookup_import_candidates(
segment.ident,
@@ -392,12 +391,16 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
candidates
.into_iter()
.filter(|candidate| {
- if let Some(def_id) = candidate.did &&
- let Some(module) = self.r.get_module(def_id) {
- Some(def_id) != self.parent_scope.module.opt_def_id() &&
- self.r.resolutions(module).borrow().iter().any(|(key, _r)| {
- key.ident.name == following_seg.ident.name
- })
+ if let Some(def_id) = candidate.did
+ && let Some(module) = self.r.get_module(def_id)
+ {
+ Some(def_id) != self.parent_scope.module.opt_def_id()
+ && self
+ .r
+ .resolutions(module)
+ .borrow()
+ .iter()
+ .any(|(key, _r)| key.ident.name == following_seg.ident.name)
} else {
false
}
@@ -747,11 +750,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
// Try to find in last block rib
- if let Some(rib) = &self.last_block_rib && let RibKind::Normal = rib.kind {
+ if let Some(rib) = &self.last_block_rib
+ && let RibKind::Normal = rib.kind
+ {
for (ident, &res) in &rib.bindings {
- if let Res::Local(_) = res && path.len() == 1 &&
- ident.span.eq_ctxt(path[0].ident.span) &&
- ident.name == path[0].ident.name {
+ if let Res::Local(_) = res
+ && path.len() == 1
+ && ident.span.eq_ctxt(path[0].ident.span)
+ && ident.name == path[0].ident.name
+ {
err.span_help(
ident.span,
format!("the binding `{path_str}` is available in a different scope in the same function"),
@@ -867,9 +874,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// (could be in a different file) or introduced in the same file as the typo
// (could belong to a different crate)
if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
- && res
- .opt_def_id()
- .is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
+ && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
{
err.span_label(
sugg_span,
@@ -1074,12 +1079,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&& trait_ref.path.span == span
&& let PathSource::Trait(_) = source
&& let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
- && let Ok(self_ty_str) =
- self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
+ && let Ok(self_ty_str) = self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
&& let Ok(trait_ref_str) =
self.r.tcx.sess.source_map().span_to_snippet(trait_ref.path.span)
{
- err.multipart_suggestion(
+ err.multipart_suggestion(
"`impl` items mention the trait being implemented first and the type it is being implemented for second",
vec![(trait_ref.path.span, self_ty_str), (self_ty.span, trait_ref_str)],
Applicability::MaybeIncorrect,
@@ -1106,12 +1110,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
source: PathSource<'_>,
span: Span,
) -> bool {
- if let PathSource::Expr(_) = source &&
- let Some(Expr {
- span: expr_span,
- kind: ExprKind::Assign(lhs, _, _),
- ..
- }) = self.diagnostic_metadata.in_if_condition {
+ if let PathSource::Expr(_) = source
+ && let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }) =
+ self.diagnostic_metadata.in_if_condition
+ {
// Icky heuristic so we don't suggest:
// `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
// `if 2 = i` => `if let 2 = i` (lhs needs to contain error span)
@@ -1240,31 +1242,32 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let mut has_self_arg = None;
if let PathSource::Expr(Some(parent)) = source
&& let ExprKind::Call(_, args) = &parent.kind
- && !args.is_empty() {
- let mut expr_kind = &args[0].kind;
- loop {
- match expr_kind {
- ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
- if arg_name.segments[0].ident.name == kw::SelfLower {
- let call_span = parent.span;
- let tail_args_span = if args.len() > 1 {
- Some(Span::new(
- args[1].span.lo(),
- args.last().unwrap().span.hi(),
- call_span.ctxt(),
- None,
- ))
- } else {
- None
- };
- has_self_arg = Some((call_span, tail_args_span));
- }
- break;
+ && !args.is_empty()
+ {
+ let mut expr_kind = &args[0].kind;
+ loop {
+ match expr_kind {
+ ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
+ if arg_name.segments[0].ident.name == kw::SelfLower {
+ let call_span = parent.span;
+ let tail_args_span = if args.len() > 1 {
+ Some(Span::new(
+ args[1].span.lo(),
+ args.last().unwrap().span.hi(),
+ call_span.ctxt(),
+ None,
+ ))
+ } else {
+ None
+ };
+ has_self_arg = Some((call_span, tail_args_span));
}
- ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
- _ => break,
+ break;
}
+ ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
+ _ => break,
}
+ }
}
has_self_arg
}
@@ -1321,8 +1324,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
true
} else if kind == DefKind::Struct
- && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
- && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
+ && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
+ && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
{
// The LHS is a type that originates from a macro call.
// We have to add angle brackets around it.
@@ -1427,7 +1430,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
.map(|(idx, new)| (new, old_fields.get(idx)))
.map(|(new, old)| {
let new = new.to_ident_string();
- if let Some(Some(old)) = old && new != *old { format!("{new}: {old}") } else { new }
+ if let Some(Some(old)) = old
+ && new != *old
+ {
+ format!("{new}: {old}")
+ } else {
+ new
+ }
})
.collect::<Vec<String>>()
} else {
@@ -1561,7 +1570,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err.set_primary_message(
"cannot initialize a tuple struct which contains private fields",
);
-
+ if !def_id.is_local()
+ && self
+ .r
+ .tcx
+ .inherent_impls(def_id)
+ .iter()
+ .flat_map(|impl_def_id| {
+ self.r.tcx.provided_trait_methods(*impl_def_id)
+ })
+ .any(|assoc| !assoc.fn_has_self_parameter && assoc.name == sym::new)
+ {
+ // FIXME: look for associated functions with Self return type,
+ // instead of relying only on the name and lack of self receiver.
+ err.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ "you might have meant to use the `new` associated function",
+ "::new".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
// Use spans of the tuple struct definition.
self.r.field_def_ids(def_id).map(|field_ids| {
field_ids
@@ -1813,7 +1841,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
- if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) {
+ if let RibKind::MacroDefinition(def) = rib.kind
+ && def == self.r.macro_def(ctxt)
+ {
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ctxt.remove_mark();
@@ -1934,18 +1964,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// try to give a suggestion for this pattern: `name = blah`, which is common in other languages
// suggest `let name = blah` to introduce a new binding
fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool {
- if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment &&
- let ast::ExprKind::Path(None, _) = lhs.kind {
- if !ident_span.from_expansion() {
- err.span_suggestion_verbose(
- ident_span.shrink_to_lo(),
- "you might have meant to introduce a new binding",
- "let ".to_string(),
- Applicability::MaybeIncorrect,
- );
- return true;
- }
+ if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) =
+ self.diagnostic_metadata.in_assignment
+ && let ast::ExprKind::Path(None, _) = lhs.kind
+ {
+ if !ident_span.from_expansion() {
+ err.span_suggestion_verbose(
+ ident_span.shrink_to_lo(),
+ "you might have meant to introduce a new binding",
+ "let ".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ return true;
}
+ }
false
}
@@ -2406,7 +2438,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
continue;
}
- if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name {
+ if !span.can_be_used_for_suggestions()
+ && suggest_note
+ && let Some(name) = name
+ {
suggest_note = false; // Avoid displaying the same help multiple times.
err.span_label(
span,