Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 86 additions & 27 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,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 @@ -773,6 +774,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
if could_be_path {
// let mut import_suggestions = self.lookup_import_candidates(
let import_suggestions = self.lookup_import_candidates(
name,
Namespace::ValueNS,
Expand Down Expand Up @@ -869,11 +871,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if import_suggestions.is_empty() && !suggested_typo {
let help_msg = format!(
"if you meant to match on a unit struct, unit variant or a `const` \
item, consider making the path in the pattern qualified: \
item, consider making the path in the pattern qualified: \
`path::to::ModOrType::{name}`",
);
err.span_help(span, help_msg);
}

show_candidates(
self.tcx,
&mut err,
Expand Down Expand Up @@ -1370,6 +1373,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) -> Vec<ImportSuggestion>
where
FilterFn: Fn(Res) -> bool,
{
self.lookup_import_candidates_from_module_impl(
lookup_ident,
namespace,
parent_scope,
start_module,
crate_path,
|ident, lookup_ident| ident.name == lookup_ident.name,
filter_fn,
)
}
fn lookup_import_candidates_from_module_impl<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();
let mut seen_modules = FxHashSet::default();
Expand Down Expand Up @@ -1440,7 +1467,9 @@ 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
let is_exact_match = ident_filter_fn(ident.orig(orig_ident_span), lookup_ident);
// let is_exact_match = ident.name == lookup_ident.name;
if is_exact_match
&& ns == namespace
&& in_module != parent_scope.module
&& ident.ctxt.is_root()
Expand Down Expand Up @@ -1520,6 +1549,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
note,
via_import,
is_stable,
is_exact_match,
});
}
}
Expand Down Expand Up @@ -1596,6 +1626,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).
///
/// An _impl variant allows to apply a filter function on the ident themselves.
pub(crate) fn lookup_import_candidates<FilterFn>(
&mut self,
lookup_ident: Ident,
Expand All @@ -1605,14 +1637,35 @@ 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,
)
}
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(
let mut suggestions = self.lookup_import_candidates_from_module_impl(
lookup_ident,
namespace,
parent_scope,
self.graph_root.to_module(),
crate_path,
&ident_filter_fn,
&filter_fn,
);

Expand Down Expand Up @@ -3537,7 +3590,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 @@ -3573,6 +3626,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 @@ -3582,6 +3636,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 @@ -3612,27 +3667,29 @@ fn show_candidates(
}

if !accessible_path_strings.is_empty() {
let (determiner, kind, s, name, through) =
if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
(
"this",
*descr,
"",
format!(" `{name}`"),
if *via_import { " through its public re-export" } else { "" },
)
} else {
// Get the unique item kinds and if there's only one, we use the right kind name
// instead of the more generic "items".
let kinds = accessible_path_strings
.iter()
.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" };
let (determiner, kind, s, name, through) = if let [
(name, descr, _, _, via_import, _is_exact_match),
] = &accessible_path_strings[..]
{
(
"this",
*descr,
"",
format!(" `{name}`"),
if *via_import { " through its public re-export" } else { "" },
)
} else {
// Get the unique item kinds and if there's only one, we use the right kind name
// instead of the more generic "items".
let kinds = accessible_path_strings
.iter()
.map(|(_, descr, _, _, _, _is_exact_match)| *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" };

("one of these", kind, s, String::new(), "")
};
("one of these", kind, s, String::new(), "")
};

let instead = if let Instead::Yes = instead { " instead" } else { "" };
let mut msg = if let DiagMode::Pattern = mode {
Expand Down Expand Up @@ -3725,7 +3782,9 @@ 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",
if let DiagMode::Pattern = mode { ", which" } else { "" }
Expand All @@ -3745,7 +3804,7 @@ fn show_candidates(
} else {
let descr = inaccessible_path_strings
.iter()
.map(|&(_, descr, _, _, _)| descr)
.map(|&(_, descr, _, _, _, _is_exact_match)| descr)
.all_equal_value()
.unwrap_or("item");
let plural_descr =
Expand All @@ -3755,7 +3814,7 @@ fn show_candidates(
let mut has_colon = false;

let mut spans = Vec::new();
for (name, _, source_span, _, _) in &inaccessible_path_strings {
for (name, _, source_span, _, _, _is_exact_match) 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
12 changes: 12 additions & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5596,6 +5596,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