summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late/diagnostics.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_resolve/src/late/diagnostics.rs
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_resolve/src/late/diagnostics.rs')
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs204
1 files changed, 124 insertions, 80 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index b8ddc4552..37fbfad2d 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -19,9 +19,8 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::PrimTy;
-use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::Session;
@@ -167,13 +166,6 @@ impl TypoCandidate {
}
impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
- fn def_span(&self, def_id: DefId) -> Option<Span> {
- match def_id.krate {
- LOCAL_CRATE => self.r.opt_span(def_id),
- _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.tcx.sess)),
- }
- }
-
fn make_base_error(
&mut self,
path: &[Segment],
@@ -192,7 +184,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
span,
span_label: match res {
Res::Def(kind, def_id) if kind == DefKind::TyParam => {
- self.def_span(def_id).map(|span| (span, "found this type parameter"))
+ Some((self.r.def_span(def_id), "found this type parameter"))
}
_ => None,
},
@@ -1296,28 +1288,46 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = find_span(&source, err);
- if let Some(span) = self.def_span(def_id) {
- err.span_label(span, &format!("`{}` defined here", path_str));
- }
- let (tail, descr, applicability) = match source {
- PathSource::Pat | PathSource::TupleStruct(..) => {
- ("", "pattern", Applicability::MachineApplicable)
- }
- _ => (": val", "literal", Applicability::HasPlaceholders),
- };
- let (fields, applicability) = match self.r.field_names.get(&def_id) {
- Some(fields) => (
- fields
- .iter()
- .map(|f| format!("{}{}", f.node, tail))
- .collect::<Vec<String>>()
- .join(", "),
- applicability,
+ err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
+
+ let (tail, descr, applicability, old_fields) = match source {
+ PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None),
+ PathSource::TupleStruct(_, args) => (
+ "",
+ "pattern",
+ Applicability::MachineApplicable,
+ Some(
+ args.iter()
+ .map(|a| self.r.tcx.sess.source_map().span_to_snippet(*a).ok())
+ .collect::<Vec<Option<String>>>(),
+ ),
),
+ _ => (": val", "literal", Applicability::HasPlaceholders, None),
+ };
+ let field_ids = self.r.field_def_ids(def_id);
+ let (fields, applicability) = match field_ids {
+ Some(field_ids) => {
+ let fields = field_ids.iter().map(|&id| self.r.tcx.item_name(id));
+
+ let fields = if let Some(old_fields) = old_fields {
+ fields
+ .enumerate()
+ .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 }
+ })
+ .collect::<Vec<String>>()
+ } else {
+ fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>()
+ };
+
+ (fields.join(", "), applicability)
+ }
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
};
- let pad = match self.r.field_names.get(&def_id) {
- Some(fields) if fields.is_empty() => "",
+ let pad = match field_ids {
+ Some(field_ids) if field_ids.is_empty() => "",
_ => " ",
};
err.span_suggestion(
@@ -1360,17 +1370,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if self.r.tcx.sess.is_nightly_build() {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
- if let Some(span) = self.def_span(def_id) {
- if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
- // The span contains a type alias so we should be able to
- // replace `type` with `trait`.
- let snip = snip.replacen("type", "trait", 1);
- err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
- } else {
- err.span_help(span, msg);
- }
+ let span = self.r.def_span(def_id);
+ if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
+ // The span contains a type alias so we should be able to
+ // replace `type` with `trait`.
+ let snip = snip.replacen("type", "trait", 1);
+ err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
} else {
- err.help(msg);
+ err.span_help(span, msg);
}
}
}
@@ -1409,19 +1416,38 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
self.suggest_using_enum_variant(err, source, def_id, span);
}
(Res::Def(DefKind::Struct, def_id), source) if ns == ValueNS => {
- let (ctor_def, ctor_vis, fields) =
- if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() {
- if let PathSource::Expr(Some(parent)) = source {
- if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
- bad_struct_syntax_suggestion(def_id);
- return true;
- }
+ let struct_ctor = match def_id.as_local() {
+ Some(def_id) => self.r.struct_constructors.get(&def_id).cloned(),
+ None => {
+ let ctor = self.r.cstore().ctor_untracked(def_id);
+ ctor.map(|(ctor_kind, ctor_def_id)| {
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
+ let ctor_vis = self.r.tcx.visibility(ctor_def_id);
+ let field_visibilities = self
+ .r
+ .tcx
+ .associated_item_def_ids(def_id)
+ .iter()
+ .map(|field_id| self.r.tcx.visibility(field_id))
+ .collect();
+ (ctor_res, ctor_vis, field_visibilities)
+ })
+ }
+ };
+
+ let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
+ if let PathSource::Expr(Some(parent)) = source {
+ if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
+ bad_struct_syntax_suggestion(def_id);
+ return true;
}
- struct_ctor
- } else {
- bad_struct_syntax_suggestion(def_id);
- return true;
- };
+ }
+ struct_ctor
+ } else {
+ bad_struct_syntax_suggestion(def_id);
+ return true;
+ };
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
if !is_expected(ctor_def) || is_accessible {
@@ -1445,10 +1471,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
// Use spans of the tuple struct definition.
- self.r
- .field_names
- .get(&def_id)
- .map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
+ self.r.field_def_ids(def_id).map(|field_ids| {
+ field_ids
+ .iter()
+ .map(|&field_id| self.r.def_span(field_id))
+ .collect::<Vec<_>>()
+ })
}
_ => None,
};
@@ -1494,9 +1522,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
match source {
PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
let span = find_span(&source, err);
- if let Some(span) = self.def_span(def_id) {
- err.span_label(span, &format!("`{}` defined here", path_str));
- }
+ err.span_label(
+ self.r.def_span(def_id),
+ &format!("`{path_str}` defined here"),
+ );
err.span_suggestion(
span,
"use this syntax instead",
@@ -1508,13 +1537,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
- let def_id = self.r.parent(ctor_def_id);
- if let Some(span) = self.def_span(def_id) {
- err.span_label(span, &format!("`{}` defined here", path_str));
- }
- let fields = self.r.field_names.get(&def_id).map_or_else(
+ let def_id = self.r.tcx.parent(ctor_def_id);
+ err.span_label(self.r.def_span(def_id), &format!("`{path_str}` defined here"));
+ let fields = self.r.field_def_ids(def_id).map_or_else(
|| "/* fields */".to_string(),
- |fields| vec!["_"; fields.len()].join(", "),
+ |field_ids| vec!["_"; field_ids.len()].join(", "),
);
err.span_suggestion(
span,
@@ -1595,8 +1622,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
resolution.full_res()
{
- if let Some(field_names) = self.r.field_names.get(&did) {
- if field_names.iter().any(|&field_name| ident.name == field_name.node) {
+ if let Some(field_ids) = self.r.field_def_ids(did) {
+ if field_ids
+ .iter()
+ .any(|&field_id| ident.name == self.r.tcx.item_name(field_id))
+ {
return Some(AssocSuggestion::Field);
}
}
@@ -1631,7 +1661,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
) {
let res = binding.res();
if filter_fn(res) {
- if self.r.has_self.contains(&res.def_id()) {
+ let def_id = res.def_id();
+ let has_self = match def_id.as_local() {
+ Some(def_id) => self.r.has_self.contains(&def_id),
+ None => self
+ .r
+ .tcx
+ .fn_arg_names(def_id)
+ .first()
+ .map_or(false, |ident| ident.name == kw::SelfLower),
+ };
+ if has_self {
return Some(AssocSuggestion::MethodWithSelf { called });
} else {
match res {
@@ -1737,7 +1777,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let name = path[path.len() - 1].ident.name;
// Make sure error reporting is deterministic.
- names.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap());
+ names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
match find_best_match_for_name(
&names.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
@@ -1999,12 +2039,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
} else {
let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
- let def_id = self.r.parent(ctor_def_id);
- let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty());
+ let def_id = self.r.tcx.parent(ctor_def_id);
match kind {
CtorKind::Const => false,
- CtorKind::Fn if has_no_fields => false,
- _ => true,
+ CtorKind::Fn => !self
+ .r
+ .field_def_ids(def_id)
+ .map_or(false, |field_ids| field_ids.is_empty()),
}
};
@@ -2065,15 +2106,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
};
if def_id.is_local() {
- if let Some(span) = self.def_span(def_id) {
- err.span_note(span, "the enum is defined here");
- }
+ err.span_note(self.r.def_span(def_id), "the enum is defined here");
}
}
- pub(crate) fn report_missing_type_error(
+ pub(crate) fn suggest_adding_generic_parameter(
&self,
path: &[Segment],
+ source: PathSource<'_>,
) -> Option<(Span, &'static str, String, Applicability)> {
let (ident, span) = match path {
[segment]
@@ -2109,7 +2149,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// Without the 2nd `true`, we'd suggest `impl <T>` for `impl T` when a type `T` isn't found
| (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true)
| (Some(Item { kind, .. }), false, _) => {
- // Likely missing type parameter.
if let Some(generics) = kind.generics() {
if span.overlaps(generics.span) {
// Avoid the following:
@@ -2122,7 +2161,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// | not found in this scope
return None;
}
- let msg = "you might be missing a type parameter";
+
+ let (msg, sugg) = match source {
+ PathSource::Type => ("you might be missing a type parameter", ident),
+ PathSource::Expr(_) => ("you might be missing a const parameter", format!("const {ident}: /* Type */")),
+ _ => return None,
+ };
let (span, sugg) = if let [.., param] = &generics.params[..] {
let span = if let [.., bound] = &param.bounds[..] {
bound.span()
@@ -2133,9 +2177,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else {
param.ident.span
};
- (span, format!(", {}", ident))
+ (span, format!(", {sugg}"))
} else {
- (generics.span, format!("<{}>", ident))
+ (generics.span, format!("<{sugg}>"))
};
// Do not suggest if this is coming from macro expansion.
if span.can_be_used_for_suggestions() {