Skip to content

Commit 7341785

Browse files
committed
Refactor out the common functionality of
`resolve_item_in_lexical_scope` and `resolve_identifier_in_local_ribs` into a new function `resolve_ident_in_lexical_scope`.
1 parent 07fecf8 commit 7341785

File tree

1 file changed

+61
-52
lines changed

1 file changed

+61
-52
lines changed

src/librustc_resolve/lib.rs

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@ impl LocalDef {
784784
}
785785
}
786786

787+
enum LexicalScopeBinding<'a> {
788+
Item(&'a NameBinding<'a>),
789+
LocalDef(LocalDef),
790+
}
791+
787792
/// The link from a module up to its nearest parent node.
788793
#[derive(Clone,Debug)]
789794
enum ParentLink<'a> {
@@ -1430,40 +1435,66 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14301435
span)
14311436
}
14321437

1433-
/// This function resolves `name` in `namespace` in the current lexical scope, returning
1434-
/// Success(binding) if `name` resolves to an item, or Failed(None) if `name` does not resolve
1435-
/// or resolves to a type parameter or local variable.
1436-
/// n.b. `resolve_identifier_in_local_ribs` also resolves names in the current lexical scope.
1438+
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
1439+
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
1440+
/// `ident` in the first scope that defines it (or None if no scopes define it).
1441+
///
1442+
/// A block's items are above its local variables in the scope hierarchy, regardless of where
1443+
/// the items are defined in the block. For example,
1444+
/// ```rust
1445+
/// fn f() {
1446+
/// g(); // Since there are no local variables in scope yet, this resolves to the item.
1447+
/// let g = || {};
1448+
/// fn g() {}
1449+
/// g(); // This resolves to the local variable `g` since it shadows the item.
1450+
/// }
1451+
/// ```
14371452
///
14381453
/// Invariant: This must only be called during main resolution, not during
14391454
/// import resolution.
1440-
fn resolve_item_in_lexical_scope(&mut self,
1441-
name: Name,
1442-
namespace: Namespace,
1443-
record_used: bool)
1444-
-> ResolveResult<&'a NameBinding<'a>> {
1455+
fn resolve_ident_in_lexical_scope(&mut self,
1456+
ident: hir::Ident,
1457+
ns: Namespace,
1458+
record_used: bool)
1459+
-> Option<LexicalScopeBinding<'a>> {
1460+
let name = match ns { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
1461+
14451462
// Walk backwards up the ribs in scope.
1446-
for i in (0 .. self.get_ribs(namespace).len()).rev() {
1447-
if let Some(_) = self.get_ribs(namespace)[i].bindings.get(&name).cloned() {
1448-
// The name resolves to a type parameter or local variable, so return Failed(None).
1449-
return Failed(None);
1450-
}
1451-
1452-
if let ModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
1453-
if let Success(binding) = self.resolve_name_in_module(module,
1454-
name,
1455-
namespace,
1456-
true,
1457-
record_used) {
1458-
// The name resolves to an item.
1459-
return Success(binding);
1463+
for i in (0 .. self.get_ribs(ns).len()).rev() {
1464+
if let Some(def) = self.get_ribs(ns)[i].bindings.get(&name).cloned() {
1465+
// The ident resolves to a type parameter or local variable.
1466+
return Some(LexicalScopeBinding::LocalDef(LocalDef {
1467+
ribs: Some((ns, i)),
1468+
def: def,
1469+
}));
1470+
}
1471+
1472+
if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind {
1473+
let name = ident.unhygienic_name;
1474+
let item = self.resolve_name_in_module(module, name, ns, true, record_used);
1475+
if let Success(binding) = item {
1476+
// The ident resolves to an item.
1477+
return Some(LexicalScopeBinding::Item(binding));
14601478
}
1479+
14611480
// We can only see through anonymous modules
1462-
if module.def.is_some() { return Failed(None); }
1481+
if module.def.is_some() { return None; }
14631482
}
14641483
}
14651484

1466-
Failed(None)
1485+
None
1486+
}
1487+
1488+
fn resolve_item_in_lexical_scope(&mut self,
1489+
name: Name,
1490+
namespace: Namespace,
1491+
record_used: bool)
1492+
-> ResolveResult<&'a NameBinding<'a>> {
1493+
let ident = hir::Ident::from_name(name);
1494+
match self.resolve_ident_in_lexical_scope(ident, namespace, record_used) {
1495+
Some(LexicalScopeBinding::Item(binding)) => Success(binding),
1496+
_ => Failed(None),
1497+
}
14671498
}
14681499

14691500
/// Returns the nearest normal module parent of the given module.
@@ -2861,33 +2892,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28612892
namespace: Namespace,
28622893
record_used: bool)
28632894
-> Option<LocalDef> {
2864-
// Check the local set of ribs.
2865-
let name = match namespace { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
2866-
2867-
for i in (0 .. self.get_ribs(namespace).len()).rev() {
2868-
if let Some(def) = self.get_ribs(namespace)[i].bindings.get(&name).cloned() {
2869-
return Some(LocalDef {
2870-
ribs: Some((namespace, i)),
2871-
def: def,
2872-
});
2873-
}
2874-
2875-
if let ModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
2876-
if let Success(binding) = self.resolve_name_in_module(module,
2877-
ident.unhygienic_name,
2878-
namespace,
2879-
true,
2880-
record_used) {
2881-
if let Some(def) = binding.def() {
2882-
return Some(LocalDef::from_def(def));
2883-
}
2884-
}
2885-
// We can only see through anonymous modules
2886-
if module.def.is_some() { return None; }
2887-
}
2888-
}
2889-
2890-
None
2895+
Some(match self.resolve_ident_in_lexical_scope(ident, namespace, record_used) {
2896+
Some(LexicalScopeBinding::LocalDef(local_def)) => local_def,
2897+
Some(LexicalScopeBinding::Item(binding)) => LocalDef::from_def(binding.def().unwrap()),
2898+
None => return None,
2899+
})
28912900
}
28922901

28932902
fn with_no_errors<T, F>(&mut self, f: F) -> T

0 commit comments

Comments
 (0)