Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a15dfca5
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,发现更多精彩内容 >>
提交
a15dfca5
编写于
6月 22, 2016
作者:
J
Jeffrey Seyfried
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Instead of renaming, treat differently marked identifiers as unequal
上级
ca924047
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
37 addition
and
560 deletion
+37
-560
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+26
-27
src/libsyntax/ast.rs
src/libsyntax/ast.rs
+1
-36
src/libsyntax/ext/base.rs
src/libsyntax/ext/base.rs
+0
-4
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+7
-423
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/mtwt.rs
+3
-58
src/libsyntax/parse/token.rs
src/libsyntax/parse/token.rs
+0
-12
未找到文件。
src/librustc_resolve/lib.rs
浏览文件 @
a15dfca5
...
...
@@ -53,7 +53,6 @@
use
rustc
::
hir
::{
Freevar
,
FreevarMap
,
TraitCandidate
,
TraitMap
,
GlobMap
};
use
rustc
::
util
::
nodemap
::{
NodeMap
,
NodeSet
,
FnvHashMap
,
FnvHashSet
};
use
syntax
::
ext
::
mtwt
;
use
syntax
::
ast
::{
self
,
FloatTy
};
use
syntax
::
ast
::{
CRATE_NODE_ID
,
Name
,
NodeId
,
CrateNum
,
IntTy
,
UintTy
};
use
syntax
::
parse
::
token
::{
self
,
keywords
};
...
...
@@ -462,7 +461,7 @@ struct BindingInfo {
}
// Map from the name in a pattern to its binding mode.
type
BindingMap
=
HashMap
<
Name
,
BindingInfo
>
;
type
BindingMap
=
HashMap
<
ast
::
Ident
,
BindingInfo
>
;
#[derive(Copy,
Clone,
PartialEq,
Eq,
Debug)]
enum
PatternSource
{
...
...
@@ -668,7 +667,7 @@ enum ModulePrefixResult<'a> {
/// One local scope.
#[derive(Debug)]
struct
Rib
<
'a
>
{
bindings
:
HashMap
<
Name
,
Def
>
,
bindings
:
HashMap
<
ast
::
Ident
,
Def
>
,
kind
:
RibKind
<
'a
>
,
}
...
...
@@ -1385,15 +1384,17 @@ fn resolve_module_path(&mut self,
/// Invariant: This must only be called during main resolution, not during
/// import resolution.
fn
resolve_ident_in_lexical_scope
(
&
mut
self
,
ident
:
ast
::
Ident
,
mut
ident
:
ast
::
Ident
,
ns
:
Namespace
,
record_used
:
bool
)
->
Option
<
LexicalScopeBinding
<
'a
>>
{
let
name
=
match
ns
{
ValueNS
=>
mtwt
::
resolve
(
ident
),
TypeNS
=>
ident
.name
};
if
ns
==
TypeNS
{
ident
=
ast
::
Ident
::
with_empty_ctxt
(
ident
.name
);
}
// Walk backwards up the ribs in scope.
for
i
in
(
0
..
self
.get_ribs
(
ns
)
.len
())
.rev
()
{
if
let
Some
(
def
)
=
self
.get_ribs
(
ns
)[
i
]
.bindings
.get
(
&
name
)
.cloned
()
{
if
let
Some
(
def
)
=
self
.get_ribs
(
ns
)[
i
]
.bindings
.get
(
&
ident
)
.cloned
()
{
// The ident resolves to a type parameter or local variable.
return
Some
(
LexicalScopeBinding
::
LocalDef
(
LocalDef
{
ribs
:
Some
((
ns
,
i
)),
...
...
@@ -1556,7 +1557,7 @@ fn with_scope<F>(&mut self, id: NodeId, f: F)
/// Searches the current set of local scopes for labels.
/// Stops after meeting a closure.
fn
search_label
(
&
self
,
name
:
Name
)
->
Option
<
Def
>
{
fn
search_label
(
&
self
,
ident
:
ast
::
Ident
)
->
Option
<
Def
>
{
for
rib
in
self
.label_ribs
.iter
()
.rev
()
{
match
rib
.kind
{
NormalRibKind
=>
{
...
...
@@ -1567,7 +1568,7 @@ fn search_label(&self, name: Name) -> Option<Def> {
return
None
;
}
}
let
result
=
rib
.bindings
.get
(
&
name
)
.cloned
();
let
result
=
rib
.bindings
.get
(
&
ident
)
.cloned
();
if
result
.is_some
()
{
return
result
;
}
...
...
@@ -1716,7 +1717,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
// plain insert (no renaming)
let
def_id
=
self
.definitions
.local_def_id
(
type_parameter
.id
);
let
def
=
Def
::
TyParam
(
space
,
index
as
u32
,
def_id
,
name
);
function_type_rib
.bindings
.insert
(
name
,
def
);
function_type_rib
.bindings
.insert
(
ast
::
Ident
::
with_empty_ctxt
(
name
)
,
def
);
}
self
.type_ribs
.push
(
function_type_rib
);
}
...
...
@@ -1887,7 +1888,7 @@ fn with_self_rib<F>(&mut self, self_def: Def, f: F)
let
mut
self_type_rib
=
Rib
::
new
(
NormalRibKind
);
// plain insert (no renaming, types are not currently hygienic....)
self_type_rib
.bindings
.insert
(
keywords
::
SelfType
.
name
(),
self_def
);
self_type_rib
.bindings
.insert
(
keywords
::
SelfType
.
ident
(),
self_def
);
self
.type_ribs
.push
(
self_type_rib
);
f
(
self
);
self
.type_ribs
.pop
();
...
...
@@ -1998,7 +1999,7 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
_
=>
false
,
}
{
let
binding_info
=
BindingInfo
{
span
:
ident
.span
,
binding_mode
:
binding_mode
};
binding_map
.insert
(
mtwt
::
resolve
(
ident
.node
)
,
binding_info
);
binding_map
.insert
(
ident
.node
,
binding_info
);
}
}
true
...
...
@@ -2020,15 +2021,14 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
for
(
&
key
,
&
binding_0
)
in
&
map_0
{
match
map_i
.get
(
&
key
)
{
None
=>
{
resolve_error
(
self
,
p
.span
,
ResolutionError
::
VariableNotBoundInPattern
(
key
,
1
,
i
+
1
));
let
error
=
ResolutionError
::
VariableNotBoundInPattern
(
key
.name
,
1
,
i
+
1
);
resolve_error
(
self
,
p
.span
,
error
);
}
Some
(
binding_i
)
=>
{
if
binding_0
.binding_mode
!=
binding_i
.binding_mode
{
resolve_error
(
self
,
binding_i
.span
,
ResolutionError
::
VariableBoundWithDifferentMode
(
key
,
ResolutionError
::
VariableBoundWithDifferentMode
(
key
.name
,
i
+
1
));
}
}
...
...
@@ -2039,7 +2039,7 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
if
!
map_0
.contains_key
(
&
key
)
{
resolve_error
(
self
,
binding
.span
,
ResolutionError
::
VariableNotBoundInPattern
(
key
,
i
+
1
,
1
));
ResolutionError
::
VariableNotBoundInPattern
(
key
.name
,
i
+
1
,
1
));
}
}
}
...
...
@@ -2173,16 +2173,15 @@ fn fresh_binding(&mut self,
pat_id
:
NodeId
,
outer_pat_id
:
NodeId
,
pat_src
:
PatternSource
,
bindings
:
&
mut
HashMap
<
Name
,
NodeId
>
)
bindings
:
&
mut
HashMap
<
ast
::
Ident
,
NodeId
>
)
->
PathResolution
{
// Add the binding to the local ribs, if it
// doesn't already exist in the bindings map. (We
// must not add it if it's in the bindings map
// because that breaks the assumptions later
// passes make about or-patterns.)
let
renamed
=
mtwt
::
resolve
(
ident
.node
);
let
mut
def
=
Def
::
Local
(
self
.definitions
.local_def_id
(
pat_id
),
pat_id
);
match
bindings
.get
(
&
renamed
)
.cloned
()
{
match
bindings
.get
(
&
ident
.node
)
.cloned
()
{
Some
(
id
)
if
id
==
outer_pat_id
=>
{
// `Variant(a, a)`, error
resolve_error
(
...
...
@@ -2204,7 +2203,7 @@ fn fresh_binding(&mut self,
Some
(
..
)
if
pat_src
==
PatternSource
::
Match
=>
{
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
def
=
self
.value_ribs
.last_mut
()
.unwrap
()
.bindings
[
&
renamed
];
def
=
self
.value_ribs
.last_mut
()
.unwrap
()
.bindings
[
&
ident
.node
];
}
Some
(
..
)
=>
{
span_bug!
(
ident
.span
,
"two bindings with the same name from
\
...
...
@@ -2213,8 +2212,8 @@ fn fresh_binding(&mut self,
None
=>
{
// A completely fresh binding, add to the lists if it's valid.
if
ident
.node.name
!=
keywords
::
Invalid
.name
()
{
bindings
.insert
(
renamed
,
outer_pat_id
);
self
.value_ribs
.last_mut
()
.unwrap
()
.bindings
.insert
(
renamed
,
def
);
bindings
.insert
(
ident
.node
,
outer_pat_id
);
self
.value_ribs
.last_mut
()
.unwrap
()
.bindings
.insert
(
ident
.node
,
def
);
}
}
}
...
...
@@ -2275,7 +2274,7 @@ fn resolve_pattern(&mut self,
pat_src
:
PatternSource
,
// Maps idents to the node ID for the
// outermost pattern that binds them.
bindings
:
&
mut
HashMap
<
Name
,
NodeId
>
)
{
bindings
:
&
mut
HashMap
<
ast
::
Ident
,
NodeId
>
)
{
// Visit all direct subpatterns of this pattern.
let
outer_pat_id
=
pat
.id
;
pat
.walk
(
&
mut
|
pat
|
{
...
...
@@ -2748,7 +2747,7 @@ fn find_best_match(&mut self, name: &str) -> SuggestionType {
let
names
=
self
.value_ribs
.iter
()
.rev
()
.flat_map
(|
rib
|
rib
.bindings
.keys
());
.flat_map
(|
rib
|
rib
.bindings
.keys
()
.map
(|
ident
|
&
ident
.name
)
);
if
let
Some
(
found
)
=
find_best_match_for_name
(
names
,
name
,
None
)
{
if
name
!=
found
{
...
...
@@ -2759,7 +2758,7 @@ fn find_best_match(&mut self, name: &str) -> SuggestionType {
fn
resolve_labeled_block
(
&
mut
self
,
label
:
Option
<
ast
::
Ident
>
,
id
:
NodeId
,
block
:
&
Block
)
{
if
let
Some
(
label
)
=
label
{
let
(
label
,
def
)
=
(
mtwt
::
resolve
(
label
),
Def
::
Label
(
id
)
);
let
def
=
Def
::
Label
(
id
);
self
.with_label_rib
(|
this
|
{
this
.label_ribs
.last_mut
()
.unwrap
()
.bindings
.insert
(
label
,
def
);
this
.visit_block
(
block
);
...
...
@@ -2966,7 +2965,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
{
let
rib
=
this
.label_ribs
.last_mut
()
.unwrap
();
rib
.bindings
.insert
(
mtwt
::
resolve
(
label
.node
)
,
def
);
rib
.bindings
.insert
(
label
.node
,
def
);
}
visit
::
walk_expr
(
this
,
expr
);
...
...
@@ -2974,7 +2973,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
}
ExprKind
::
Break
(
Some
(
label
))
|
ExprKind
::
Continue
(
Some
(
label
))
=>
{
match
self
.search_label
(
mtwt
::
resolve
(
label
.node
)
)
{
match
self
.search_label
(
label
.node
)
{
None
=>
{
self
.record_def
(
expr
.id
,
err_path_resolution
());
resolve_error
(
self
,
...
...
src/libsyntax/ast.rs
浏览文件 @
a15dfca5
...
...
@@ -26,7 +26,6 @@
use
std
::
fmt
;
use
std
::
rc
::
Rc
;
use
std
::
hash
::{
Hash
,
Hasher
};
use
serialize
::{
Encodable
,
Decodable
,
Encoder
,
Decoder
};
/// A name is a part of an identifier, representing a string or gensym. It's
...
...
@@ -46,7 +45,7 @@
/// An identifier contains a Name (index into the interner
/// table) and a SyntaxContext to track renaming and
/// macro expansion per Flatt et al., "Macros That Work Together"
#[derive(Clone,
Copy,
Eq
)]
#[derive(Clone,
Copy,
PartialEq,
Eq,
Hash
)]
pub
struct
Ident
{
pub
name
:
Name
,
pub
ctxt
:
SyntaxContext
...
...
@@ -93,40 +92,6 @@ pub const fn with_empty_ctxt(name: Name) -> Ident {
}
}
impl
PartialEq
for
Ident
{
fn
eq
(
&
self
,
other
:
&
Ident
)
->
bool
{
if
self
.ctxt
!=
other
.ctxt
{
// There's no one true way to compare Idents. They can be compared
// non-hygienically `id1.name == id2.name`, hygienically
// `mtwt::resolve(id1) == mtwt::resolve(id2)`, or even member-wise
// `(id1.name, id1.ctxt) == (id2.name, id2.ctxt)` depending on the situation.
// Ideally, PartialEq should not be implemented for Ident at all, but that
// would be too impractical, because many larger structures (Token, in particular)
// including Idents as their parts derive PartialEq and use it for non-hygienic
// comparisons. That's why PartialEq is implemented and defaults to non-hygienic
// comparison. Hash is implemented too and is consistent with PartialEq, i.e. only
// the name of Ident is hashed. Still try to avoid comparing idents in your code
// (especially as keys in hash maps), use one of the three methods listed above
// explicitly.
//
// If you see this panic, then some idents from different contexts were compared
// non-hygienically. It's likely a bug. Use one of the three comparison methods
// listed above explicitly.
panic!
(
"idents with different contexts are compared with operator `==`:
\
{:?}, {:?}."
,
self
,
other
);
}
self
.name
==
other
.name
}
}
impl
Hash
for
Ident
{
fn
hash
<
H
:
Hasher
>
(
&
self
,
state
:
&
mut
H
)
{
self
.name
.hash
(
state
)
}
}
impl
fmt
::
Debug
for
Ident
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
write!
(
f
,
"{}#{}"
,
self
.name
,
self
.ctxt
.0
)
...
...
src/libsyntax/ext/base.rs
浏览文件 @
a15dfca5
...
...
@@ -26,7 +26,6 @@
use
ptr
::
P
;
use
util
::
small_vector
::
SmallVector
;
use
util
::
lev_distance
::
find_best_match_for_name
;
use
ext
::
mtwt
;
use
fold
::
Folder
;
use
std
::
collections
::{
HashMap
,
HashSet
};
...
...
@@ -483,15 +482,12 @@ pub enum SyntaxExtension {
pub
struct
BlockInfo
{
/// Should macros escape from this scope?
pub
macros_escape
:
bool
,
/// What are the pending renames?
pub
pending_renames
:
mtwt
::
RenameList
,
}
impl
BlockInfo
{
pub
fn
new
()
->
BlockInfo
{
BlockInfo
{
macros_escape
:
false
,
pending_renames
:
Vec
::
new
(),
}
}
}
...
...
src/libsyntax/ext/expand.rs
浏览文件 @
a15dfca5
此差异已折叠。
点击以展开。
src/libsyntax/ext/mtwt.rs
浏览文件 @
a15dfca5
...
...
@@ -17,7 +17,7 @@
pub
use
self
::
SyntaxContext_
::
*
;
use
ast
::{
Ident
,
Mrk
,
Name
,
SyntaxContext
};
use
ast
::{
Mrk
,
SyntaxContext
};
use
std
::
cell
::
RefCell
;
use
std
::
collections
::
HashMap
;
...
...
@@ -25,27 +25,19 @@
/// The SCTable contains a table of SyntaxContext_'s. It
/// represents a flattened tree structure, to avoid having
/// managed pointers everywhere (that caused an ICE).
/// the `marks` and `renames` fields are side-tables
/// that ensure that adding the same mark to the same context
/// gives you back the same context as before. This should cut
/// down on memory use *a lot*; applying a mark to a tree containing
/// 50 identifiers would otherwise generate 50 new contexts.
/// The `marks` ensures that adding the same mark to the
/// same context gives you back the same context as before.
pub
struct
SCTable
{
table
:
RefCell
<
Vec
<
SyntaxContext_
>>
,
marks
:
RefCell
<
HashMap
<
(
SyntaxContext
,
Mrk
),
SyntaxContext
>>
,
renames
:
RefCell
<
HashMap
<
Name
,
SyntaxContext
>>
,
}
#[derive(PartialEq,
RustcEncodable,
RustcDecodable,
Hash,
Debug,
Copy,
Clone)]
pub
enum
SyntaxContext_
{
EmptyCtxt
,
Mark
(
Mrk
,
SyntaxContext
),
Rename
(
Name
),
}
/// A list of ident->name renamings
pub
type
RenameList
=
Vec
<
(
Ident
,
Name
)
>
;
/// Extend a syntax context with a given mark
pub
fn
apply_mark
(
m
:
Mrk
,
ctxt
:
SyntaxContext
)
->
SyntaxContext
{
with_sctable
(|
table
|
apply_mark_internal
(
m
,
ctxt
,
table
))
...
...
@@ -63,32 +55,6 @@ fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxCo
}
}
/// Extend a syntax context with a given rename
pub
fn
apply_rename
(
from
:
Ident
,
to
:
Name
,
ident
:
Ident
)
->
Ident
{
with_sctable
(|
table
|
apply_rename_internal
(
from
,
to
,
ident
,
table
))
}
/// Extend a syntax context with a given rename and sctable (explicit memoization)
fn
apply_rename_internal
(
from
:
Ident
,
to
:
Name
,
ident
:
Ident
,
table
:
&
SCTable
)
->
Ident
{
if
(
ident
.name
,
ident
.ctxt
)
!=
(
from
.name
,
from
.ctxt
)
{
return
ident
;
}
let
ctxt
=
*
table
.renames
.borrow_mut
()
.entry
(
to
)
.or_insert_with
(||
{
SyntaxContext
(
idx_push
(
&
mut
*
table
.table
.borrow_mut
(),
Rename
(
to
)))
});
Ident
{
ctxt
:
ctxt
,
..
ident
}
}
/// Apply a list of renamings to a context
// if these rename lists get long, it would make sense
// to consider memoizing this fold. This may come up
// when we add hygiene to item names.
pub
fn
apply_renames
(
renames
:
&
RenameList
,
ident
:
Ident
)
->
Ident
{
renames
.iter
()
.fold
(
ident
,
|
ident
,
&
(
from
,
to
)|
{
apply_rename
(
from
,
to
,
ident
)
})
}
/// Fetch the SCTable from TLS, create one if it doesn't yet exist.
pub
fn
with_sctable
<
T
,
F
>
(
op
:
F
)
->
T
where
F
:
FnOnce
(
&
SCTable
)
->
T
,
...
...
@@ -102,7 +68,6 @@ fn new_sctable_internal() -> SCTable {
SCTable
{
table
:
RefCell
::
new
(
vec!
[
EmptyCtxt
]),
marks
:
RefCell
::
new
(
HashMap
::
new
()),
renames
:
RefCell
::
new
(
HashMap
::
new
()),
}
}
...
...
@@ -119,7 +84,6 @@ pub fn clear_tables() {
with_sctable
(|
table
|
{
*
table
.table
.borrow_mut
()
=
Vec
::
new
();
*
table
.marks
.borrow_mut
()
=
HashMap
::
new
();
*
table
.renames
.borrow_mut
()
=
HashMap
::
new
();
});
}
...
...
@@ -128,7 +92,6 @@ pub fn reset_tables() {
with_sctable
(|
table
|
{
*
table
.table
.borrow_mut
()
=
vec!
[
EmptyCtxt
];
*
table
.marks
.borrow_mut
()
=
HashMap
::
new
();
*
table
.renames
.borrow_mut
()
=
HashMap
::
new
();
});
}
...
...
@@ -138,24 +101,6 @@ fn idx_push<T>(vec: &mut Vec<T>, val: T) -> u32 {
(
vec
.len
()
-
1
)
as
u32
}
/// Resolve a syntax object to a name, per MTWT.
pub
fn
resolve
(
id
:
Ident
)
->
Name
{
with_sctable
(|
sctable
|
{
resolve_internal
(
id
,
sctable
)
})
}
/// Resolve a syntax object to a name, per MTWT.
/// adding memoization to resolve 500+ seconds in resolve for librustc (!)
fn
resolve_internal
(
id
:
Ident
,
table
:
&
SCTable
)
->
Name
{
match
table
.table
.borrow
()[
id
.ctxt
.0
as
usize
]
{
EmptyCtxt
=>
id
.name
,
// ignore marks here:
Mark
(
_
,
subctxt
)
=>
resolve_internal
(
Ident
::
new
(
id
.name
,
subctxt
),
table
),
Rename
(
name
)
=>
name
,
}
}
/// Return the outer mark for a context with a mark at the outside.
/// FAILS when outside is not a mark.
pub
fn
outer_mark
(
ctxt
:
SyntaxContext
)
->
Mrk
{
...
...
src/libsyntax/parse/token.rs
浏览文件 @
a15dfca5
...
...
@@ -15,7 +15,6 @@
pub
use
self
::
Token
::
*
;
use
ast
::{
self
,
BinOpKind
};
use
ext
::
mtwt
;
use
ptr
::
P
;
use
util
::
interner
::{
RcStr
,
StrInterner
};
use
util
::
interner
;
...
...
@@ -313,17 +312,6 @@ pub fn is_reserved_keyword(&self) -> bool {
_
=>
false
,
}
}
/// Hygienic identifier equality comparison.
///
/// See `styntax::ext::mtwt`.
pub
fn
mtwt_eq
(
&
self
,
other
:
&
Token
)
->
bool
{
match
(
self
,
other
)
{
(
&
Ident
(
id1
),
&
Ident
(
id2
))
|
(
&
Lifetime
(
id1
),
&
Lifetime
(
id2
))
=>
mtwt
::
resolve
(
id1
)
==
mtwt
::
resolve
(
id2
),
_
=>
*
self
==
*
other
}
}
}
#[derive(Clone,
RustcEncodable,
RustcDecodable,
PartialEq,
Eq,
Hash)]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录