Skip to content
Open
77 changes: 64 additions & 13 deletions compiler/rustc_resolve/src/error_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub(crate) struct ImportSuggestion {
/// An extra note that should be issued if this item is suggested
pub note: Option<String>,
pub is_stable: bool,
pub is_exact_match: bool,
}

/// Adjust the impl span so that just the `impl` keyword is taken by removing
Expand Down Expand Up @@ -1594,16 +1595,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

fn lookup_import_candidates_from_module<FilterFn>(
fn lookup_import_candidates_from_module<IdentFilterFn, FilterFn>(
&self,
lookup_ident: Ident,
namespace: Namespace,
parent_scope: &ParentScope<'ra>,
start_module: Module<'ra>,
crate_path: ThinVec<ast::PathSegment>,
ident_filter_fn: IdentFilterFn,
filter_fn: FilterFn,
) -> Vec<ImportSuggestion>
where
IdentFilterFn: Fn(Ident, Ident) -> bool,
FilterFn: Fn(Res) -> bool,
{
let mut candidates = Vec::new();
Expand Down Expand Up @@ -1675,7 +1678,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// collect results based on the filter function
// avoid suggesting anything from the same module in which we are resolving
// avoid suggesting anything with a hygienic name
if ident.name == lookup_ident.name
if ident_filter_fn(ident.orig(orig_ident_span), lookup_ident)
&& ns == namespace
&& in_module != parent_scope.module
&& ident.ctxt.is_root()
Expand Down Expand Up @@ -1755,6 +1758,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
note,
via_import,
is_stable,
is_exact_match: ident.name == lookup_ident.name,
});
}
}
Expand Down Expand Up @@ -1831,6 +1835,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
///
/// N.B., the method does not look into imports, but this is not a problem,
/// since we report the definitions (thus, the de-aliased imports).
///
/// The method is implemented in `lookup_import_candidates_impl`. The `_impl` method allows applying a different filter function on the ident than the exact match function used by default here.
pub(crate) fn lookup_import_candidates<FilterFn>(
&mut self,
lookup_ident: Ident,
Expand All @@ -1840,6 +1846,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) -> Vec<ImportSuggestion>
where
FilterFn: Fn(Res) -> bool,
{
self.lookup_import_candidates_impl(
lookup_ident,
namespace,
parent_scope,
|ident: Ident, lookup_ident: Ident| ident.name == lookup_ident.name,
filter_fn,
)
}

/// The actual impl of the `lookup_import_candidates function`.
pub(crate) fn lookup_import_candidates_impl<IdentFilterFn, FilterFn>(
&mut self,
lookup_ident: Ident,
namespace: Namespace,
parent_scope: &ParentScope<'ra>,
ident_filter_fn: IdentFilterFn,
filter_fn: FilterFn,
) -> Vec<ImportSuggestion>
where
IdentFilterFn: Fn(Ident, Ident) -> bool,
FilterFn: Fn(Res) -> bool,
{
let crate_path = thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];
let mut suggestions = self.lookup_import_candidates_from_module(
Expand All @@ -1848,6 +1876,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
self.graph_root.to_module(),
crate_path,
&ident_filter_fn,
&filter_fn,
);

Expand Down Expand Up @@ -1904,6 +1933,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
crate_root,
crate_path,
&ident_filter_fn,
&filter_fn,
));
}
Expand Down Expand Up @@ -3803,7 +3833,7 @@ pub(crate) fn import_candidates(
);
}

type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool, bool);

/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
Expand Down Expand Up @@ -3839,6 +3869,7 @@ fn show_candidates(
c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
&c.note,
c.via_import,
c.is_exact_match,
))
}
} else {
Expand All @@ -3848,6 +3879,7 @@ fn show_candidates(
c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
&c.note,
c.via_import,
c.is_exact_match,
))
}
});
Expand Down Expand Up @@ -3879,9 +3911,10 @@ fn show_candidates(

if !accessible_path_strings.is_empty() {
let (determiner, kind, s, name, through) =
if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
if let [(name, descr, _, _, via_import, is_exact_match)] = &accessible_path_strings[..]
{
(
"this",
if *is_exact_match { "this" } else { "this similarly named" },
*descr,
"",
format!(" `{name}`"),
Expand All @@ -3892,12 +3925,24 @@ fn show_candidates(
// instead of the more generic "items".
let kinds = accessible_path_strings
.iter()
.map(|(_, descr, _, _, _)| *descr)
.map(|(_, descr, _, _, _, _)| *descr)
.collect::<UnordSet<&str>>();
let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
let s = if kind.ends_with('s') { "es" } else { "s" };
// we should only suggest case insensitive suggestion if no case sensitive match was found,
// so all the suggestion should have the same is_exact_match value.

("one of these", kind, s, String::new(), "")
(
if accessible_path_strings[0].5 {
"one of these"
} else {
"one of these similarly named"
},
kind,
s,
String::new(),
"",
)
};

let instead = if let Instead::Yes = instead { " instead" } else { "" };
Expand Down Expand Up @@ -3991,9 +4036,12 @@ fn show_candidates(
{
let prefix =
if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
if let [(name, descr, source_span, note, _, is_exact_match)] =
&inaccessible_path_strings[..]
{
let msg = format!(
"{prefix}{descr} `{name}`{} exists but is inaccessible",
"{prefix}{}{descr} `{name}`{} exists but is inaccessible",
if *is_exact_match { "" } else { "similarly named " },
if let DiagMode::Pattern = mode { ", which" } else { "" }
);

Expand All @@ -4011,17 +4059,20 @@ fn show_candidates(
} else {
let descr = inaccessible_path_strings
.iter()
.map(|&(_, descr, _, _, _)| descr)
.map(|&(_, descr, _, _, _, _)| descr)
.all_equal_value()
.unwrap_or("item");
let plural_descr =
if descr.ends_with('s') { format!("{descr}es") } else { format!("{descr}s") };

let mut msg = format!("{prefix}these {plural_descr} exist but are inaccessible");
let are_exact_matches = inaccessible_path_strings[0].5;
let mut msg = format!(
"{prefix}these {}{plural_descr} exist but are inaccessible",
if are_exact_matches { "" } else { "similarly named " },
);
let mut has_colon = false;

let mut spans = Vec::new();
for (name, _, source_span, _, _) in &inaccessible_path_strings {
for (name, _, source_span, _, _, _) in &inaccessible_path_strings {
if let Some(source_span) = source_span {
let span = tcx.sess.source_map().guess_head_span(*source_span);
spans.push((name, span));
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ impl RibKind<'_> {
#[derive(Debug)]
pub(crate) struct Rib<'ra, R = Res> {
pub bindings: FxIndexMap<Ident, R>,
pub patterns_with_skipped_bindings: UnordMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
pub patterns_with_skipped_bindings:
UnordMap<DefId, Vec<(Span, Option<Span>, Result<(), ErrorGuaranteed>)>>,
pub kind: RibKind<'ra>,
}

Expand Down Expand Up @@ -4374,6 +4375,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
.or_default()
.push((
pat.span,
match rest {
ast::PatFieldsRest::Rest(span) => Some(*span),
_ => None,
},
match rest {
ast::PatFieldsRest::Recovered(guar) => Err(*guar),
_ => Ok(()),
Expand Down Expand Up @@ -5686,6 +5691,18 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
.filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
.count();
self.r.item_generics_num_lifetimes.insert(def_id, count);
let type_or_const_count = generics
.params
.iter()
.filter(|param| {
matches!(
param.kind,
ast::GenericParamKind::Type { .. }
| ast::GenericParamKind::Const { .. }
)
})
.count();
self.r.item_generics_num_type_or_const_params.insert(def_id, type_or_const_count);
}

ItemKind::ForeignMod(ForeignMod { items, .. }) => {
Expand Down
Loading
Loading