Skip to content

Commit 6162529

Browse files
committed
Auto merge of rust-lang#89100 - petrochenkov:localbind, r=cjgillot
resolve: Use `NameBinding` for local variables and generic parameters `NameBinding` is a structure used for representing any name introduction (an item, or import, or even a built-in). Except that local variables and generic parameters weren't represented as `NameBinding`s, for this reason they requires separate paths in name resolution code in several places. This PR introduces `NameBinding`s for local variables as well and simplifies all the code working with them leaving only the `NameBinding` paths.
2 parents 42983a2 + c1e8fc8 commit 6162529

File tree

3 files changed

+145
-213
lines changed

3 files changed

+145
-213
lines changed

compiler/rustc_resolve/src/late.rs

+87-74
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use RibKind::*;
99

10-
use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
10+
use crate::{path_names_to_string, BindingError, CrateLint, NameBinding, ToNameBinding};
1111
use crate::{Module, ModuleOrUniformRoot, ParentScope, PathResult};
1212
use crate::{ResolutionError, Resolver, Segment, UseError};
1313

@@ -21,27 +21,22 @@ use rustc_hir::def::Namespace::{self, *};
2121
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
2222
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
2323
use rustc_hir::{PrimTy, TraitCandidate};
24-
use rustc_middle::{bug, span_bug};
24+
use rustc_middle::{bug, span_bug, ty};
2525
use rustc_session::lint;
26+
use rustc_span::source_map::{respan, Spanned};
2627
use rustc_span::symbol::{kw, sym, Ident, Symbol};
27-
use rustc_span::Span;
28+
use rustc_span::{Span, DUMMY_SP};
2829
use smallvec::{smallvec, SmallVec};
30+
use tracing::debug;
2931

30-
use rustc_span::source_map::{respan, Spanned};
3132
use std::collections::{hash_map::Entry, BTreeSet};
3233
use std::mem::{replace, take};
33-
use tracing::debug;
3434

3535
mod diagnostics;
3636
crate mod lifetimes;
3737

3838
type Res = def::Res<NodeId>;
3939

40-
type IdentMap<T> = FxHashMap<Ident, T>;
41-
42-
/// Map from the name in a pattern to its binding mode.
43-
type BindingMap = IdentMap<BindingInfo>;
44-
4540
#[derive(Copy, Clone, Debug)]
4641
struct BindingInfo {
4742
span: Span,
@@ -172,8 +167,8 @@ impl RibKind<'_> {
172167
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
173168
/// resolving, the name is looked up from inside out.
174169
#[derive(Debug)]
175-
crate struct Rib<'a, R = Res> {
176-
pub bindings: IdentMap<R>,
170+
crate struct Rib<'a, R = &'a NameBinding<'a>> {
171+
pub bindings: FxHashMap<Ident, R>,
177172
pub kind: RibKind<'a>,
178173
}
179174

@@ -567,12 +562,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
567562
GenericParamKind::Type { .. } => {
568563
forward_ty_ban_rib
569564
.bindings
570-
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
565+
.insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding);
571566
}
572567
GenericParamKind::Const { .. } => {
573568
forward_const_ban_rib
574569
.bindings
575-
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
570+
.insert(Ident::with_dummy_span(param.ident.name), self.r.dummy_binding);
576571
}
577572
GenericParamKind::Lifetime => {}
578573
}
@@ -589,7 +584,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
589584
// such as in the case of `trait Add<Rhs = Self>`.)
590585
if self.diagnostic_metadata.current_self_item.is_some() {
591586
// (`Some` if + only if we are in ADT's generics.)
592-
forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
587+
forward_ty_ban_rib
588+
.bindings
589+
.insert(Ident::with_dummy_span(kw::SelfUpper), self.r.dummy_binding);
593590
}
594591

595592
for param in &generics.params {
@@ -737,15 +734,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
737734
ns: Namespace,
738735
record_used_id: Option<NodeId>,
739736
path_span: Span,
740-
) -> Option<LexicalScopeBinding<'a>> {
741-
self.r.resolve_ident_in_lexical_scope(
742-
ident,
743-
ns,
744-
&self.parent_scope,
745-
record_used_id,
746-
path_span,
747-
&self.ribs[ns],
748-
)
737+
) -> Option<&'a NameBinding<'a>> {
738+
self.r
739+
.resolve_ident_in_lexical_scope(
740+
ident,
741+
ns,
742+
&self.parent_scope,
743+
record_used_id,
744+
path_span,
745+
&self.ribs[ns],
746+
)
747+
.ok()
749748
}
750749

751750
fn resolve_path(
@@ -903,6 +902,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
903902
}
904903

905904
fn future_proof_import(&mut self, use_tree: &UseTree) {
905+
if !self.should_report_errs() {
906+
return;
907+
}
908+
906909
let segments = &use_tree.prefix.segments;
907910
if !segments.is_empty() {
908911
let ident = segments[0].ident;
@@ -914,31 +917,42 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
914917
UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
915918
_ => &[TypeNS],
916919
};
920+
921+
let from_ribs = |binding: &NameBinding<'_>| {
922+
matches!(
923+
binding.res(),
924+
Res::Local(..)
925+
| Res::SelfTy(..)
926+
| Res::Def(DefKind::TyParam | DefKind::ConstParam, ..)
927+
)
928+
};
917929
let report_error = |this: &Self, ns| {
918930
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
919-
if this.should_report_errs() {
920-
this.r
921-
.session
922-
.span_err(ident.span, &format!("imports cannot refer to {}", what));
923-
}
931+
let msg = format!("imports cannot refer to {what}");
932+
this.r.session.span_err(ident.span, &msg);
924933
};
925934

926935
for &ns in nss {
927-
match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
928-
Some(LexicalScopeBinding::Res(..)) => {
936+
if let Some(binding) =
937+
self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span)
938+
{
939+
if from_ribs(binding) {
929940
report_error(self, ns);
930-
}
931-
Some(LexicalScopeBinding::Item(binding)) => {
941+
} else {
932942
let orig_unusable_binding =
933943
replace(&mut self.r.unusable_binding, Some(binding));
934-
if let Some(LexicalScopeBinding::Res(..)) = self
935-
.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span)
936-
{
937-
report_error(self, ns);
944+
if let Some(binding) = self.resolve_ident_in_lexical_scope(
945+
ident,
946+
ns,
947+
None,
948+
use_tree.prefix.span,
949+
) {
950+
if from_ribs(binding) {
951+
report_error(self, ns);
952+
}
938953
}
939954
self.r.unusable_binding = orig_unusable_binding;
940955
}
941-
None => {}
942956
}
943957
}
944958
} else if let UseTreeKind::Nested(use_trees) = &use_tree.kind {
@@ -1135,8 +1149,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
11351149
_ => unreachable!(),
11361150
};
11371151
let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id());
1152+
let binding =
1153+
(res, ty::Visibility::Invisible, param.ident.span, self.parent_scope.expansion)
1154+
.to_name_binding(self.r.arenas);
1155+
11381156
self.r.record_partial_res(param.id, PartialRes::new(res));
1139-
rib.bindings.insert(ident, res);
1157+
rib.bindings.insert(ident, binding);
11401158
}
11411159

11421160
self.ribs[ValueNS].push(function_value_rib);
@@ -1256,10 +1274,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
12561274
}
12571275

12581276
fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) {
1277+
let binding = (self_res, ty::Visibility::Invisible, DUMMY_SP, self.parent_scope.expansion)
1278+
.to_name_binding(self.r.arenas);
12591279
let mut self_type_rib = Rib::new(NormalRibKind);
12601280

12611281
// Plain insert (no renaming, since types are not currently hygienic)
1262-
self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
1282+
self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), binding);
12631283
self.ribs[ns].push(self_type_rib);
12641284
f(self);
12651285
self.ribs[ns].pop();
@@ -1470,7 +1490,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14701490
/// this is done hygienically. This could arise for a macro
14711491
/// that expands into an or-pattern where one 'x' was from the
14721492
/// user and one 'x' came from the macro.
1473-
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
1493+
fn binding_mode_map(&mut self, pat: &Pat) -> FxHashMap<Ident, BindingInfo> {
14741494
let mut binding_map = FxHashMap::default();
14751495

14761496
pat.walk(&mut |pat| {
@@ -1503,7 +1523,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15031523

15041524
/// Checks that all of the arms in an or-pattern have exactly the
15051525
/// same set of bindings, with the same binding modes for each.
1506-
fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
1526+
fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<FxHashMap<Ident, BindingInfo>> {
15071527
let mut missing_vars = FxHashMap::default();
15081528
let mut inconsistent_vars = FxHashMap::default();
15091529

@@ -1645,7 +1665,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
16451665
.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
16461666
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
16471667
self.r.record_partial_res(pat.id, PartialRes::new(res));
1648-
self.r.record_pat_span(pat.id, pat.span);
16491668
}
16501669
PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
16511670
self.smart_resolve_path(
@@ -1735,18 +1754,24 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17351754
if already_bound_or {
17361755
// `Variant1(a) | Variant2(a)`, ok
17371756
// Reuse definition from the first `a`.
1738-
self.innermost_rib_bindings(ValueNS)[&ident]
1757+
self.innermost_rib_bindings(ValueNS)[&ident].res()
17391758
} else {
17401759
let res = Res::Local(pat_id);
17411760
if ident_valid {
17421761
// A completely fresh binding add to the set if it's valid.
1743-
self.innermost_rib_bindings(ValueNS).insert(ident, res);
1762+
let binding =
1763+
(res, ty::Visibility::Invisible, ident.span, self.parent_scope.expansion)
1764+
.to_name_binding(self.r.arenas);
1765+
self.innermost_rib_bindings(ValueNS).insert(ident, binding);
17441766
}
17451767
res
17461768
}
17471769
}
17481770

1749-
fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
1771+
fn innermost_rib_bindings(
1772+
&mut self,
1773+
ns: Namespace,
1774+
) -> &mut FxHashMap<Ident, &'a NameBinding<'a>> {
17501775
&mut self.ribs[ns].last_mut().unwrap().bindings
17511776
}
17521777

@@ -1763,32 +1788,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17631788
// also be interpreted as a path to e.g. a constant, variant, etc.
17641789
let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
17651790

1766-
let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
1767-
let (res, binding) = match ls_binding {
1768-
LexicalScopeBinding::Item(binding)
1769-
if is_syntactic_ambiguity && binding.is_ambiguity() =>
1770-
{
1771-
// For ambiguous bindings we don't know all their definitions and cannot check
1772-
// whether they can be shadowed by fresh bindings or not, so force an error.
1773-
// issues/33118#issuecomment-233962221 (see below) still applies here,
1774-
// but we have to ignore it for backward compatibility.
1775-
self.r.record_use(ident, binding, false);
1776-
return None;
1777-
}
1778-
LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
1779-
LexicalScopeBinding::Res(res) => (res, None),
1780-
};
1791+
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
1792+
if is_syntactic_ambiguity && binding.is_ambiguity() {
1793+
// For ambiguous bindings we don't know all their definitions and cannot check
1794+
// whether they can be shadowed by fresh bindings or not, so force an error.
1795+
// issues/33118#issuecomment-233962221 (see below) still applies here,
1796+
// but we have to ignore it for backward compatibility.
1797+
self.r.record_use(ident, binding, false);
1798+
return None;
1799+
}
17811800

1801+
let res = binding.res();
17821802
match res {
17831803
Res::SelfCtor(_) // See #70549.
17841804
| Res::Def(
17851805
DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::ConstParam,
17861806
_,
17871807
) if is_syntactic_ambiguity => {
17881808
// Disambiguate in favor of a unit struct/variant or constant pattern.
1789-
if let Some(binding) = binding {
1790-
self.r.record_use(ident, binding, false);
1791-
}
1809+
self.r.record_use(ident, binding, false);
17921810
Some(res)
17931811
}
17941812
Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static, _) => {
@@ -1797,7 +1815,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17971815
// to something unusable as a pattern (e.g., constructor function),
17981816
// but we still conservatively report an error, see
17991817
// issues/33118#issuecomment-233962221 for one reason why.
1800-
let binding = binding.expect("no binding for a ctor or static");
18011818
self.report_error(
18021819
ident.span,
18031820
ResolutionError::BindingShadowsSomethingUnacceptable {
@@ -2037,19 +2054,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
20372054
}
20382055

20392056
fn self_type_is_available(&mut self, span: Span) -> bool {
2040-
let binding = self.resolve_ident_in_lexical_scope(
2041-
Ident::with_dummy_span(kw::SelfUpper),
2042-
TypeNS,
2043-
None,
2044-
span,
2045-
);
2046-
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
2057+
let ident = Ident::with_dummy_span(kw::SelfUpper);
2058+
self.resolve_ident_in_lexical_scope(ident, TypeNS, None, span)
2059+
.map_or(false, |binding| binding.res() != Res::Err)
20472060
}
20482061

20492062
fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool {
20502063
let ident = Ident::new(kw::SelfLower, self_span);
2051-
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span);
2052-
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
2064+
self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span)
2065+
.map_or(false, |binding| binding.res() != Res::Err)
20532066
}
20542067

20552068
/// A wrapper around [`Resolver::report_error`].

compiler/rustc_resolve/src/late/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
12941294
// Walk backwards up the ribs in scope and collect candidates.
12951295
for rib in self.ribs[ns].iter().rev() {
12961296
// Locals and type parameters
1297-
for (ident, &res) in &rib.bindings {
1297+
for (ident, binding) in &rib.bindings {
1298+
let res = binding.res();
12981299
if filter_fn(res) {
12991300
names.push(TypoSuggestion::typo_from_res(ident.name, res));
13001301
}

0 commit comments

Comments
 (0)