Skip to content

Commit c340ea1

Browse files
committed
Auto merge of #29547 - arielb1:speculative-upvar, r=eddyb
`resolve_identifier` used to mark a variable as an upvar when used within a closure. However, the function is also used for the "unnecessary qualification" lint, which would mark paths whose last component had the same name as a local as upvars. Fixes #29522 r? @eddyb
2 parents 708e319 + ca04855 commit c340ea1

File tree

3 files changed

+194
-151
lines changed

3 files changed

+194
-151
lines changed

src/librustc_resolve/lib.rs

+149-151
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use rustc::front::map as hir_map;
5353
use rustc::session::Session;
5454
use rustc::lint;
5555
use rustc::metadata::csearch;
56-
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
56+
use rustc::metadata::decoder::{DefLike, DlDef};
5757
use rustc::middle::def::*;
5858
use rustc::middle::def_id::DefId;
5959
use rustc::middle::pat_util::pat_bindings_hygienic;
@@ -652,6 +652,21 @@ impl Rib {
652652
}
653653
}
654654

655+
/// A definition along with the index of the rib it was found on
656+
struct LocalDef {
657+
ribs: Option<(Namespace, usize)>,
658+
def: Def
659+
}
660+
661+
impl LocalDef {
662+
fn from_def(def: Def) -> Self {
663+
LocalDef {
664+
ribs: None,
665+
def: def
666+
}
667+
}
668+
}
669+
655670
/// The link from a module up to its nearest parent node.
656671
#[derive(Clone,Debug)]
657672
enum ParentLink {
@@ -1954,116 +1969,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
19541969
self.current_module = orig_module;
19551970
}
19561971

1957-
/// Wraps the given definition in the appropriate number of `DefUpvar`
1958-
/// wrappers.
1959-
fn upvarify(&self,
1960-
ribs: &[Rib],
1961-
def_like: DefLike,
1962-
span: Span)
1963-
-> Option<DefLike> {
1964-
let mut def = match def_like {
1965-
DlDef(def) => def,
1966-
_ => return Some(def_like)
1967-
};
1968-
match def {
1969-
DefUpvar(..) => {
1970-
self.session.span_bug(span,
1971-
&format!("unexpected {:?} in bindings", def))
1972-
}
1973-
DefLocal(_, node_id) => {
1974-
for rib in ribs {
1975-
match rib.kind {
1976-
NormalRibKind => {
1977-
// Nothing to do. Continue.
1978-
}
1979-
ClosureRibKind(function_id) => {
1980-
let prev_def = def;
1981-
let node_def_id = self.ast_map.local_def_id(node_id);
1982-
1983-
let mut seen = self.freevars_seen.borrow_mut();
1984-
let seen = seen.entry(function_id).or_insert_with(|| NodeMap());
1985-
if let Some(&index) = seen.get(&node_id) {
1986-
def = DefUpvar(node_def_id, node_id, index, function_id);
1987-
continue;
1988-
}
1989-
let mut freevars = self.freevars.borrow_mut();
1990-
let vec = freevars.entry(function_id)
1991-
.or_insert_with(|| vec![]);
1992-
let depth = vec.len();
1993-
vec.push(Freevar { def: prev_def, span: span });
1994-
1995-
def = DefUpvar(node_def_id, node_id, depth, function_id);
1996-
seen.insert(node_id, depth);
1997-
}
1998-
ItemRibKind | MethodRibKind => {
1999-
// This was an attempt to access an upvar inside a
2000-
// named function item. This is not allowed, so we
2001-
// report an error.
2002-
resolve_error(
2003-
self,
2004-
span,
2005-
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem
2006-
);
2007-
return None;
2008-
}
2009-
ConstantItemRibKind => {
2010-
// Still doesn't deal with upvars
2011-
resolve_error(
2012-
self,
2013-
span,
2014-
ResolutionError::AttemptToUseNonConstantValueInConstant
2015-
);
2016-
return None;
2017-
}
2018-
}
2019-
}
2020-
}
2021-
DefTyParam(..) | DefSelfTy(..) => {
2022-
for rib in ribs {
2023-
match rib.kind {
2024-
NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
2025-
// Nothing to do. Continue.
2026-
}
2027-
ItemRibKind => {
2028-
// This was an attempt to use a type parameter outside
2029-
// its scope.
2030-
2031-
resolve_error(self,
2032-
span,
2033-
ResolutionError::TypeParametersFromOuterFunction);
2034-
return None;
2035-
}
2036-
ConstantItemRibKind => {
2037-
// see #9186
2038-
resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
2039-
return None;
2040-
}
2041-
}
2042-
}
2043-
}
2044-
_ => {}
2045-
}
2046-
Some(DlDef(def))
2047-
}
2048-
2049-
/// Searches the current set of local scopes and
2050-
/// applies translations for closures.
2051-
fn search_ribs(&self,
2052-
ribs: &[Rib],
2053-
name: Name,
2054-
span: Span)
2055-
-> Option<DefLike> {
2056-
// FIXME #4950: Try caching?
2057-
2058-
for (i, rib) in ribs.iter().enumerate().rev() {
2059-
if let Some(def_like) = rib.bindings.get(&name).cloned() {
2060-
return self.upvarify(&ribs[i + 1..], def_like, span);
2061-
}
2062-
}
2063-
2064-
None
2065-
}
2066-
20671972
/// Searches the current set of local scopes for labels.
20681973
/// Stops after meeting a closure.
20691974
fn search_label(&self, name: Name) -> Option<DefLike> {
@@ -3123,19 +3028,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31233028
}
31243029

31253030
// Try to find a path to an item in a module.
3126-
let unqualified_def =
3127-
self.resolve_identifier(segments.last().unwrap().identifier,
3128-
namespace,
3129-
check_ribs,
3130-
span);
3031+
let unqualified_def = self.resolve_identifier(
3032+
segments.last().unwrap().identifier,
3033+
namespace, check_ribs);
31313034

31323035
if segments.len() <= 1 {
3133-
return unqualified_def.map(mk_res);
3036+
return unqualified_def
3037+
.and_then(|def| self.adjust_local_def(def, span))
3038+
.map(|def| {
3039+
PathResolution::new(def, LastMod(AllPublic), path_depth)
3040+
});
31343041
}
31353042

31363043
let def = self.resolve_module_relative_path(span, segments, namespace);
31373044
match (def, unqualified_def) {
3138-
(Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
3045+
(Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
31393046
self.session
31403047
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
31413048
id, span,
@@ -3147,31 +3054,119 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31473054
def.map(mk_res)
31483055
}
31493056

3150-
// Resolve a single identifier.
3057+
// Resolve a single identifier
31513058
fn resolve_identifier(&mut self,
31523059
identifier: Ident,
31533060
namespace: Namespace,
3154-
check_ribs: bool,
3155-
span: Span)
3156-
-> Option<(Def, LastPrivate)> {
3061+
check_ribs: bool)
3062+
-> Option<LocalDef> {
31573063
// First, check to see whether the name is a primitive type.
31583064
if namespace == TypeNS {
31593065
if let Some(&prim_ty) = self.primitive_type_table
31603066
.primitive_types
31613067
.get(&identifier.name) {
3162-
return Some((DefPrimTy(prim_ty), LastMod(AllPublic)));
3068+
return Some(LocalDef::from_def(DefPrimTy(prim_ty)));
31633069
}
31643070
}
31653071

31663072
if check_ribs {
31673073
if let Some(def) = self.resolve_identifier_in_local_ribs(identifier,
3168-
namespace,
3169-
span) {
3170-
return Some((def, LastMod(AllPublic)));
3074+
namespace) {
3075+
return Some(def);
31713076
}
31723077
}
31733078

31743079
self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace)
3080+
.map(LocalDef::from_def)
3081+
}
3082+
3083+
// Resolve a local definition, potentially adjusting for closures.
3084+
fn adjust_local_def(&self, local_def: LocalDef, span: Span) -> Option<Def> {
3085+
let ribs = match local_def.ribs {
3086+
Some((TypeNS, i)) => &self.type_ribs[i+1..],
3087+
Some((ValueNS, i)) => &self.value_ribs[i+1..],
3088+
_ => &[] as &[_]
3089+
};
3090+
let mut def = local_def.def;
3091+
match def {
3092+
DefUpvar(..) => {
3093+
self.session.span_bug(span,
3094+
&format!("unexpected {:?} in bindings", def))
3095+
}
3096+
DefLocal(_, node_id) => {
3097+
for rib in ribs {
3098+
match rib.kind {
3099+
NormalRibKind => {
3100+
// Nothing to do. Continue.
3101+
}
3102+
ClosureRibKind(function_id) => {
3103+
let prev_def = def;
3104+
let node_def_id = self.ast_map.local_def_id(node_id);
3105+
3106+
let mut seen = self.freevars_seen.borrow_mut();
3107+
let seen = seen.entry(function_id).or_insert_with(|| NodeMap());
3108+
if let Some(&index) = seen.get(&node_id) {
3109+
def = DefUpvar(node_def_id, node_id, index, function_id);
3110+
continue;
3111+
}
3112+
let mut freevars = self.freevars.borrow_mut();
3113+
let vec = freevars.entry(function_id)
3114+
.or_insert_with(|| vec![]);
3115+
let depth = vec.len();
3116+
vec.push(Freevar { def: prev_def, span: span });
3117+
3118+
def = DefUpvar(node_def_id, node_id, depth, function_id);
3119+
seen.insert(node_id, depth);
3120+
}
3121+
ItemRibKind | MethodRibKind => {
3122+
// This was an attempt to access an upvar inside a
3123+
// named function item. This is not allowed, so we
3124+
// report an error.
3125+
resolve_error(
3126+
self,
3127+
span,
3128+
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem
3129+
);
3130+
return None;
3131+
}
3132+
ConstantItemRibKind => {
3133+
// Still doesn't deal with upvars
3134+
resolve_error(
3135+
self,
3136+
span,
3137+
ResolutionError::AttemptToUseNonConstantValueInConstant
3138+
);
3139+
return None;
3140+
}
3141+
}
3142+
}
3143+
}
3144+
DefTyParam(..) | DefSelfTy(..) => {
3145+
for rib in ribs {
3146+
match rib.kind {
3147+
NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
3148+
// Nothing to do. Continue.
3149+
}
3150+
ItemRibKind => {
3151+
// This was an attempt to use a type parameter outside
3152+
// its scope.
3153+
3154+
resolve_error(self,
3155+
span,
3156+
ResolutionError::TypeParametersFromOuterFunction);
3157+
return None;
3158+
}
3159+
ConstantItemRibKind => {
3160+
// see #9186
3161+
resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
3162+
return None;
3163+
}
3164+
}
3165+
}
3166+
}
3167+
_ => {}
3168+
}
3169+
return Some(def);
31753170
}
31763171

31773172
// FIXME #4952: Merge me with resolve_name_in_module?
@@ -3364,38 +3359,41 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
33643359

33653360
fn resolve_identifier_in_local_ribs(&mut self,
33663361
ident: Ident,
3367-
namespace: Namespace,
3368-
span: Span)
3369-
-> Option<Def> {
3362+
namespace: Namespace)
3363+
-> Option<LocalDef> {
33703364
// Check the local set of ribs.
3371-
let search_result = match namespace {
3372-
ValueNS => {
3373-
let renamed = mtwt::resolve(ident);
3374-
self.search_ribs(&self.value_ribs, renamed, span)
3375-
}
3376-
TypeNS => {
3377-
let name = ident.name;
3378-
self.search_ribs(&self.type_ribs, name, span)
3379-
}
3365+
let (name, ribs) = match namespace {
3366+
ValueNS => (mtwt::resolve(ident), &self.value_ribs),
3367+
TypeNS => (ident.name, &self.type_ribs)
33803368
};
33813369

3382-
match search_result {
3383-
Some(DlDef(def)) => {
3384-
debug!("(resolving path in local ribs) resolved `{}` to local: {:?}",
3385-
ident,
3386-
def);
3387-
Some(def)
3388-
}
3389-
Some(DlField) | Some(DlImpl(_)) | None => {
3390-
None
3370+
for (i, rib) in ribs.iter().enumerate().rev() {
3371+
if let Some(def_like) = rib.bindings.get(&name).cloned() {
3372+
match def_like {
3373+
DlDef(def) => {
3374+
debug!("(resolving path in local ribs) resolved `{}` to {:?} at {}",
3375+
name, def, i);
3376+
return Some(LocalDef {
3377+
ribs: Some((namespace, i)),
3378+
def: def
3379+
});
3380+
}
3381+
def_like => {
3382+
debug!("(resolving path in local ribs) resolved `{}` to pseudo-def {:?}",
3383+
name, def_like);
3384+
return None;
3385+
}
3386+
}
33913387
}
33923388
}
3389+
3390+
None
33933391
}
33943392

33953393
fn resolve_item_by_name_in_lexical_scope(&mut self,
33963394
name: Name,
33973395
namespace: Namespace)
3398-
-> Option<(Def, LastPrivate)> {
3396+
-> Option<Def> {
33993397
// Check the items.
34003398
let module = self.current_module.clone();
34013399
match self.resolve_item_in_lexical_scope(module,
@@ -3409,7 +3407,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
34093407
debug!("(resolving item path by identifier in lexical \
34103408
scope) failed to resolve {} after success...",
34113409
name);
3412-
return None;
3410+
None
34133411
}
34143412
Some(def) => {
34153413
debug!("(resolving item path in lexical scope) \
@@ -3418,7 +3416,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
34183416
// This lookup is "all public" because it only searched
34193417
// for one identifier in the current module (couldn't
34203418
// have passed through reexports or anything like that.
3421-
return Some((def, LastMod(AllPublic)));
3419+
Some(def)
34223420
}
34233421
}
34243422
}
@@ -3433,7 +3431,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
34333431
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg))
34343432
}
34353433

3436-
return None;
3434+
None
34373435
}
34383436
}
34393437
}

0 commit comments

Comments
 (0)