Skip to content

Commit 219ddde

Browse files
committed
resolve: extract try_resolve_as_non_binding.
1 parent 6d537d4 commit 219ddde

File tree

2 files changed

+69
-57
lines changed

2 files changed

+69
-57
lines changed

src/librustc_resolve/late.rs

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use GenericParameters::*;
99
use RibKind::*;
1010

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

1515
use log::debug;
@@ -1327,78 +1327,37 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
13271327
&mut self.ribs[ns].last_mut().unwrap().bindings
13281328
}
13291329

1330-
fn resolve_pattern(&mut self,
1331-
pat: &Pat,
1332-
pat_src: PatternSource,
1333-
// Maps idents to the node ID for the
1334-
// outermost pattern that binds them.
1335-
bindings: &mut FxHashMap<Ident, NodeId>) {
1330+
fn resolve_pattern(
1331+
&mut self,
1332+
pat: &Pat,
1333+
pat_src: PatternSource,
1334+
// Maps idents to the node ID for the outermost pattern that binds them.
1335+
bindings: &mut FxHashMap<Ident, NodeId>,
1336+
) {
13361337
// Visit all direct subpatterns of this pattern.
13371338
let outer_pat_id = pat.id;
13381339
pat.walk(&mut |pat| {
13391340
debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node);
13401341
match pat.node {
1341-
PatKind::Ident(bmode, ident, ref opt_pat) => {
1342-
// First try to resolve the identifier as some existing
1343-
// entity, then fall back to a fresh binding.
1344-
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
1345-
None, pat.span)
1346-
.and_then(LexicalScopeBinding::item);
1347-
let res = binding.map(NameBinding::res).and_then(|res| {
1348-
let is_syntactic_ambiguity = opt_pat.is_none() &&
1349-
bmode == BindingMode::ByValue(Mutability::Immutable);
1350-
match res {
1351-
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
1352-
Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
1353-
// Disambiguate in favor of a unit struct/variant
1354-
// or constant pattern.
1355-
self.r.record_use(ident, ValueNS, binding.unwrap(), false);
1356-
Some(res)
1357-
}
1358-
Res::Def(DefKind::Ctor(..), _)
1359-
| Res::Def(DefKind::Const, _)
1360-
| Res::Def(DefKind::Static, _) => {
1361-
// This is unambiguously a fresh binding, either syntactically
1362-
// (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
1363-
// to something unusable as a pattern (e.g., constructor function),
1364-
// but we still conservatively report an error, see
1365-
// issues/33118#issuecomment-233962221 for one reason why.
1366-
self.r.report_error(
1367-
ident.span,
1368-
ResolutionError::BindingShadowsSomethingUnacceptable(
1369-
pat_src.descr(), ident.name, binding.unwrap())
1370-
);
1371-
None
1372-
}
1373-
Res::Def(DefKind::Fn, _) | Res::Err => {
1374-
// These entities are explicitly allowed
1375-
// to be shadowed by fresh bindings.
1376-
None
1377-
}
1378-
res => {
1379-
span_bug!(ident.span, "unexpected resolution for an \
1380-
identifier in pattern: {:?}", res);
1381-
}
1382-
}
1383-
}).unwrap_or_else(|| {
1384-
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
1385-
});
1386-
1342+
PatKind::Ident(bmode, ident, ref sub) => {
1343+
// First try to resolve the identifier as some existing entity,
1344+
// then fall back to a fresh binding.
1345+
let has_sub = sub.is_some();
1346+
let res = self.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
1347+
.unwrap_or_else(|| {
1348+
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
1349+
});
13871350
self.r.record_partial_res(pat.id, PartialRes::new(res));
13881351
}
1389-
13901352
PatKind::TupleStruct(ref path, ..) => {
13911353
self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
13921354
}
1393-
13941355
PatKind::Path(ref qself, ref path) => {
13951356
self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
13961357
}
1397-
13981358
PatKind::Struct(ref path, ..) => {
13991359
self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
14001360
}
1401-
14021361
_ => {}
14031362
}
14041363
true
@@ -1407,6 +1366,58 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
14071366
visit::walk_pat(self, pat);
14081367
}
14091368

1369+
fn try_resolve_as_non_binding(
1370+
&mut self,
1371+
pat_src: PatternSource,
1372+
pat: &Pat,
1373+
bm: BindingMode,
1374+
ident: Ident,
1375+
has_sub: bool,
1376+
) -> Option<Res> {
1377+
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
1378+
let res = binding.res();
1379+
1380+
// An immutable (no `mut`) by-value (no `ref`) binding pattern without
1381+
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
1382+
// also be interpreted as a path to e.g. a constant, variant, etc.
1383+
let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable);
1384+
1385+
match res {
1386+
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
1387+
Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
1388+
// Disambiguate in favor of a unit struct/variant or constant pattern.
1389+
self.r.record_use(ident, ValueNS, binding, false);
1390+
Some(res)
1391+
}
1392+
Res::Def(DefKind::Ctor(..), _)
1393+
| Res::Def(DefKind::Const, _)
1394+
| Res::Def(DefKind::Static, _) => {
1395+
// This is unambiguously a fresh binding, either syntactically
1396+
// (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
1397+
// to something unusable as a pattern (e.g., constructor function),
1398+
// but we still conservatively report an error, see
1399+
// issues/33118#issuecomment-233962221 for one reason why.
1400+
self.r.report_error(
1401+
ident.span,
1402+
ResolutionError::BindingShadowsSomethingUnacceptable(
1403+
pat_src.descr(),
1404+
ident.name,
1405+
binding,
1406+
),
1407+
);
1408+
None
1409+
}
1410+
Res::Def(DefKind::Fn, _) | Res::Err => {
1411+
// These entities are explicitly allowed to be shadowed by fresh bindings.
1412+
None
1413+
}
1414+
res => {
1415+
span_bug!(ident.span, "unexpected resolution for an \
1416+
identifier in pattern: {:?}", res);
1417+
}
1418+
}
1419+
}
1420+
14101421
// High-level and context dependent path resolution routine.
14111422
// Resolves the path and records the resolution into definition map.
14121423
// If resolution fails tries several techniques to find likely

src/librustc_resolve/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
1010
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
1111

12+
#![feature(inner_deref)]
1213
#![feature(crate_visibility_modifier)]
1314
#![feature(label_break_value)]
1415
#![feature(mem_take)]

0 commit comments

Comments
 (0)