Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ca04855a
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ca04855a
编写于
11月 03, 2015
作者:
A
Ariel Ben-Yehuda
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
resolve: don't speculatively create freevars when resolving
Fixes #29522
上级
0152a93b
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
194 addition
and
151 deletion
+194
-151
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+149
-151
src/test/run-pass/issue-29522.rs
src/test/run-pass/issue-29522.rs
+25
-0
src/test/run-pass/resolve-pseudo-shadowing.rs
src/test/run-pass/resolve-pseudo-shadowing.rs
+20
-0
未找到文件。
src/librustc_resolve/lib.rs
浏览文件 @
ca04855a
...
...
@@ -53,7 +53,7 @@
use
rustc
::
session
::
Session
;
use
rustc
::
lint
;
use
rustc
::
metadata
::
csearch
;
use
rustc
::
metadata
::
decoder
::{
DefLike
,
DlDef
,
DlField
,
DlImpl
};
use
rustc
::
metadata
::
decoder
::{
DefLike
,
DlDef
};
use
rustc
::
middle
::
def
::
*
;
use
rustc
::
middle
::
def_id
::
DefId
;
use
rustc
::
middle
::
pat_util
::
pat_bindings_hygienic
;
...
...
@@ -652,6 +652,21 @@ fn new(kind: RibKind) -> Rib {
}
}
/// A definition along with the index of the rib it was found on
struct
LocalDef
{
ribs
:
Option
<
(
Namespace
,
usize
)
>
,
def
:
Def
}
impl
LocalDef
{
fn
from_def
(
def
:
Def
)
->
Self
{
LocalDef
{
ribs
:
None
,
def
:
def
}
}
}
/// The link from a module up to its nearest parent node.
#[derive(Clone,Debug)]
enum
ParentLink
{
...
...
@@ -1954,116 +1969,6 @@ fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
self
.current_module
=
orig_module
;
}
/// Wraps the given definition in the appropriate number of `DefUpvar`
/// wrappers.
fn
upvarify
(
&
self
,
ribs
:
&
[
Rib
],
def_like
:
DefLike
,
span
:
Span
)
->
Option
<
DefLike
>
{
let
mut
def
=
match
def_like
{
DlDef
(
def
)
=>
def
,
_
=>
return
Some
(
def_like
)
};
match
def
{
DefUpvar
(
..
)
=>
{
self
.session
.span_bug
(
span
,
&
format!
(
"unexpected {:?} in bindings"
,
def
))
}
DefLocal
(
_
,
node_id
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
=>
{
// Nothing to do. Continue.
}
ClosureRibKind
(
function_id
)
=>
{
let
prev_def
=
def
;
let
node_def_id
=
self
.ast_map
.local_def_id
(
node_id
);
let
mut
seen
=
self
.freevars_seen
.borrow_mut
();
let
seen
=
seen
.entry
(
function_id
)
.or_insert_with
(||
NodeMap
());
if
let
Some
(
&
index
)
=
seen
.get
(
&
node_id
)
{
def
=
DefUpvar
(
node_def_id
,
node_id
,
index
,
function_id
);
continue
;
}
let
mut
freevars
=
self
.freevars
.borrow_mut
();
let
vec
=
freevars
.entry
(
function_id
)
.or_insert_with
(||
vec!
[]);
let
depth
=
vec
.len
();
vec
.push
(
Freevar
{
def
:
prev_def
,
span
:
span
});
def
=
DefUpvar
(
node_def_id
,
node_id
,
depth
,
function_id
);
seen
.insert
(
node_id
,
depth
);
}
ItemRibKind
|
MethodRibKind
=>
{
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
resolve_error
(
self
,
span
,
ResolutionError
::
CannotCaptureDynamicEnvironmentInFnItem
);
return
None
;
}
ConstantItemRibKind
=>
{
// Still doesn't deal with upvars
resolve_error
(
self
,
span
,
ResolutionError
::
AttemptToUseNonConstantValueInConstant
);
return
None
;
}
}
}
}
DefTyParam
(
..
)
|
DefSelfTy
(
..
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
|
MethodRibKind
|
ClosureRibKind
(
..
)
=>
{
// Nothing to do. Continue.
}
ItemRibKind
=>
{
// This was an attempt to use a type parameter outside
// its scope.
resolve_error
(
self
,
span
,
ResolutionError
::
TypeParametersFromOuterFunction
);
return
None
;
}
ConstantItemRibKind
=>
{
// see #9186
resolve_error
(
self
,
span
,
ResolutionError
::
OuterTypeParameterContext
);
return
None
;
}
}
}
}
_
=>
{}
}
Some
(
DlDef
(
def
))
}
/// Searches the current set of local scopes and
/// applies translations for closures.
fn
search_ribs
(
&
self
,
ribs
:
&
[
Rib
],
name
:
Name
,
span
:
Span
)
->
Option
<
DefLike
>
{
// FIXME #4950: Try caching?
for
(
i
,
rib
)
in
ribs
.iter
()
.enumerate
()
.rev
()
{
if
let
Some
(
def_like
)
=
rib
.bindings
.get
(
&
name
)
.cloned
()
{
return
self
.upvarify
(
&
ribs
[
i
+
1
..
],
def_like
,
span
);
}
}
None
}
/// Searches the current set of local scopes for labels.
/// Stops after meeting a closure.
fn
search_label
(
&
self
,
name
:
Name
)
->
Option
<
DefLike
>
{
...
...
@@ -3123,19 +3028,21 @@ pub fn resolve_path(&mut self,
}
// Try to find a path to an item in a module.
let
unqualified_def
=
self
.resolve_identifier
(
segments
.last
()
.unwrap
()
.identifier
,
namespace
,
check_ribs
,
span
);
let
unqualified_def
=
self
.resolve_identifier
(
segments
.last
()
.unwrap
()
.identifier
,
namespace
,
check_ribs
);
if
segments
.len
()
<=
1
{
return
unqualified_def
.map
(
mk_res
);
return
unqualified_def
.and_then
(|
def
|
self
.adjust_local_def
(
def
,
span
))
.map
(|
def
|
{
PathResolution
::
new
(
def
,
LastMod
(
AllPublic
),
path_depth
)
});
}
let
def
=
self
.resolve_module_relative_path
(
span
,
segments
,
namespace
);
match
(
def
,
unqualified_def
)
{
(
Some
((
ref
d
,
_
)),
Some
(
(
ref
ud
,
_
)))
if
*
d
==
*
ud
=>
{
(
Some
((
ref
d
,
_
)),
Some
(
ref
ud
))
if
*
d
==
ud
.def
=>
{
self
.session
.add_lint
(
lint
::
builtin
::
UNUSED_QUALIFICATIONS
,
id
,
span
,
...
...
@@ -3147,31 +3054,119 @@ pub fn resolve_path(&mut self,
def
.map
(
mk_res
)
}
// Resolve a single identifier
.
// Resolve a single identifier
fn
resolve_identifier
(
&
mut
self
,
identifier
:
Ident
,
namespace
:
Namespace
,
check_ribs
:
bool
,
span
:
Span
)
->
Option
<
(
Def
,
LastPrivate
)
>
{
check_ribs
:
bool
)
->
Option
<
LocalDef
>
{
// First, check to see whether the name is a primitive type.
if
namespace
==
TypeNS
{
if
let
Some
(
&
prim_ty
)
=
self
.primitive_type_table
.primitive_types
.get
(
&
identifier
.name
)
{
return
Some
(
(
DefPrimTy
(
prim_ty
),
LastMod
(
AllPublic
)));
return
Some
(
LocalDef
::
from_def
(
DefPrimTy
(
prim_ty
)));
}
}
if
check_ribs
{
if
let
Some
(
def
)
=
self
.resolve_identifier_in_local_ribs
(
identifier
,
namespace
,
span
)
{
return
Some
((
def
,
LastMod
(
AllPublic
)));
namespace
)
{
return
Some
(
def
);
}
}
self
.resolve_item_by_name_in_lexical_scope
(
identifier
.name
,
namespace
)
.map
(
LocalDef
::
from_def
)
}
// Resolve a local definition, potentially adjusting for closures.
fn
adjust_local_def
(
&
self
,
local_def
:
LocalDef
,
span
:
Span
)
->
Option
<
Def
>
{
let
ribs
=
match
local_def
.ribs
{
Some
((
TypeNS
,
i
))
=>
&
self
.type_ribs
[
i
+
1
..
],
Some
((
ValueNS
,
i
))
=>
&
self
.value_ribs
[
i
+
1
..
],
_
=>
&
[]
as
&
[
_
]
};
let
mut
def
=
local_def
.def
;
match
def
{
DefUpvar
(
..
)
=>
{
self
.session
.span_bug
(
span
,
&
format!
(
"unexpected {:?} in bindings"
,
def
))
}
DefLocal
(
_
,
node_id
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
=>
{
// Nothing to do. Continue.
}
ClosureRibKind
(
function_id
)
=>
{
let
prev_def
=
def
;
let
node_def_id
=
self
.ast_map
.local_def_id
(
node_id
);
let
mut
seen
=
self
.freevars_seen
.borrow_mut
();
let
seen
=
seen
.entry
(
function_id
)
.or_insert_with
(||
NodeMap
());
if
let
Some
(
&
index
)
=
seen
.get
(
&
node_id
)
{
def
=
DefUpvar
(
node_def_id
,
node_id
,
index
,
function_id
);
continue
;
}
let
mut
freevars
=
self
.freevars
.borrow_mut
();
let
vec
=
freevars
.entry
(
function_id
)
.or_insert_with
(||
vec!
[]);
let
depth
=
vec
.len
();
vec
.push
(
Freevar
{
def
:
prev_def
,
span
:
span
});
def
=
DefUpvar
(
node_def_id
,
node_id
,
depth
,
function_id
);
seen
.insert
(
node_id
,
depth
);
}
ItemRibKind
|
MethodRibKind
=>
{
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
resolve_error
(
self
,
span
,
ResolutionError
::
CannotCaptureDynamicEnvironmentInFnItem
);
return
None
;
}
ConstantItemRibKind
=>
{
// Still doesn't deal with upvars
resolve_error
(
self
,
span
,
ResolutionError
::
AttemptToUseNonConstantValueInConstant
);
return
None
;
}
}
}
}
DefTyParam
(
..
)
|
DefSelfTy
(
..
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
|
MethodRibKind
|
ClosureRibKind
(
..
)
=>
{
// Nothing to do. Continue.
}
ItemRibKind
=>
{
// This was an attempt to use a type parameter outside
// its scope.
resolve_error
(
self
,
span
,
ResolutionError
::
TypeParametersFromOuterFunction
);
return
None
;
}
ConstantItemRibKind
=>
{
// see #9186
resolve_error
(
self
,
span
,
ResolutionError
::
OuterTypeParameterContext
);
return
None
;
}
}
}
}
_
=>
{}
}
return
Some
(
def
);
}
// FIXME #4952: Merge me with resolve_name_in_module?
...
...
@@ -3364,38 +3359,41 @@ fn resolve_crate_relative_path(&mut self,
fn
resolve_identifier_in_local_ribs
(
&
mut
self
,
ident
:
Ident
,
namespace
:
Namespace
,
span
:
Span
)
->
Option
<
Def
>
{
namespace
:
Namespace
)
->
Option
<
LocalDef
>
{
// Check the local set of ribs.
let
search_result
=
match
namespace
{
ValueNS
=>
{
let
renamed
=
mtwt
::
resolve
(
ident
);
self
.search_ribs
(
&
self
.value_ribs
,
renamed
,
span
)
}
TypeNS
=>
{
let
name
=
ident
.name
;
self
.search_ribs
(
&
self
.type_ribs
,
name
,
span
)
}
let
(
name
,
ribs
)
=
match
namespace
{
ValueNS
=>
(
mtwt
::
resolve
(
ident
),
&
self
.value_ribs
),
TypeNS
=>
(
ident
.name
,
&
self
.type_ribs
)
};
match
search_result
{
Some
(
DlDef
(
def
))
=>
{
debug!
(
"(resolving path in local ribs) resolved `{}` to local: {:?}"
,
ident
,
def
);
Some
(
def
)
}
Some
(
DlField
)
|
Some
(
DlImpl
(
_
))
|
None
=>
{
None
for
(
i
,
rib
)
in
ribs
.iter
()
.enumerate
()
.rev
()
{
if
let
Some
(
def_like
)
=
rib
.bindings
.get
(
&
name
)
.cloned
()
{
match
def_like
{
DlDef
(
def
)
=>
{
debug!
(
"(resolving path in local ribs) resolved `{}` to {:?} at {}"
,
name
,
def
,
i
);
return
Some
(
LocalDef
{
ribs
:
Some
((
namespace
,
i
)),
def
:
def
});
}
def_like
=>
{
debug!
(
"(resolving path in local ribs) resolved `{}` to pseudo-def {:?}"
,
name
,
def_like
);
return
None
;
}
}
}
}
None
}
fn
resolve_item_by_name_in_lexical_scope
(
&
mut
self
,
name
:
Name
,
namespace
:
Namespace
)
->
Option
<
(
Def
,
LastPrivate
)
>
{
->
Option
<
Def
>
{
// Check the items.
let
module
=
self
.current_module
.clone
();
match
self
.resolve_item_in_lexical_scope
(
module
,
...
...
@@ -3409,7 +3407,7 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
debug!
(
"(resolving item path by identifier in lexical
\
scope) failed to resolve {} after success..."
,
name
);
return
None
;
None
}
Some
(
def
)
=>
{
debug!
(
"(resolving item path in lexical scope)
\
...
...
@@ -3418,7 +3416,7 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
// This lookup is "all public" because it only searched
// for one identifier in the current module (couldn't
// have passed through reexports or anything like that.
return
Some
((
def
,
LastMod
(
AllPublic
)));
Some
(
def
)
}
}
}
...
...
@@ -3433,7 +3431,7 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
resolve_error
(
self
,
span
,
ResolutionError
::
FailedToResolve
(
&*
msg
))
}
return
None
;
None
}
}
}
...
...
src/test/run-pass/issue-29522.rs
0 → 100644
浏览文件 @
ca04855a
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// check that we don't accidentally capture upvars just because their name
// occurs in a path
fn
assert_static
<
T
:
'static
>
(
_
t
:
T
)
{}
mod
foo
{
pub
fn
scope
()
{}
}
fn
main
()
{
let
scope
=
&
mut
0
;
assert_static
(||
{
foo
::
scope
();
});
}
src/test/run-pass/resolve-pseudo-shadowing.rs
0 → 100644
浏览文件 @
ca04855a
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// check that type parameters can't "shadow" qualified paths.
fn
check
<
Clone
>
(
_
c
:
Clone
)
{
fn
check2
()
{
<
()
as
std
::
clone
::
Clone
>
::
clone
(
&
());
}
check2
();
}
fn
main
()
{
check
(());
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录