Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
94ef9f57
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,发现更多精彩内容 >>
提交
94ef9f57
编写于
6月 30, 2018
作者:
V
Vadim Petrochenkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
hygiene: Decouple transparencies from expansion IDs
上级
01b6d7cc
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
122 addition
and
68 deletion
+122
-68
src/libproc_macro/lib.rs
src/libproc_macro/lib.rs
+7
-12
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+4
-4
src/librustc_resolve/macros.rs
src/librustc_resolve/macros.rs
+3
-8
src/libsyntax/ext/base.rs
src/libsyntax/ext/base.rs
+6
-12
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/hygiene.rs
+44
-32
src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs
src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs
+28
-0
src/test/ui-fulldeps/proc-macro/generate-mod.rs
src/test/ui-fulldeps/proc-macro/generate-mod.rs
+21
-0
src/test/ui-fulldeps/proc-macro/generate-mod.stderr
src/test/ui-fulldeps/proc-macro/generate-mod.stderr
+9
-0
未找到文件。
src/libproc_macro/lib.rs
浏览文件 @
94ef9f57
...
...
@@ -1351,7 +1351,7 @@ pub mod __internal {
use
syntax
::
parse
::
token
::{
self
,
Token
};
use
syntax
::
tokenstream
;
use
syntax_pos
::{
BytePos
,
Loc
,
DUMMY_SP
};
use
syntax_pos
::
hygiene
::{
Mark
,
SyntaxContext
,
Transparency
};
use
syntax_pos
::
hygiene
::{
SyntaxContext
,
Transparency
};
use
super
::{
TokenStream
,
LexError
,
Span
};
...
...
@@ -1436,20 +1436,15 @@ fn drop(&mut self) {
// No way to determine def location for a proc macro right now, so use call location.
let
location
=
cx
.current_expansion.mark
.expn_info
()
.unwrap
()
.call_site
;
// Opaque mark was already created by expansion, now create its transparent twin.
// We can't use the call-site span literally here, even if it appears to provide
// correct name resolution, because it has all the `ExpnInfo` wrong, so the edition
// checks, lint macro checks, macro backtraces will all break.
let
opaque_mark
=
cx
.current_expansion.mark
;
let
transparent_mark
=
Mark
::
fresh_cloned
(
opaque_mark
);
transparent_mark
.set_transparency
(
Transparency
::
Transparent
);
let
to_span
=
|
mark
|
Span
(
location
.with_ctxt
(
SyntaxContext
::
empty
()
.apply_mark
(
mark
)));
let
to_span
=
|
transparency
|
Span
(
location
.with_ctxt
(
SyntaxContext
::
empty
()
.apply_mark_with_transparency
(
cx
.current_expansion.mark
,
transparency
))
);
p
.set
(
ProcMacroSess
{
parse_sess
:
cx
.parse_sess
,
data
:
ProcMacroData
{
def_site
:
to_span
(
opaque_mark
),
call_site
:
to_span
(
transparent_mark
),
def_site
:
to_span
(
Transparency
::
Opaque
),
call_site
:
to_span
(
Transparency
::
Transparent
),
},
});
f
()
...
...
src/librustc_resolve/lib.rs
浏览文件 @
94ef9f57
...
...
@@ -1996,8 +1996,8 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
let
mut
iter
=
ctxt
.marks
()
.into_iter
()
.rev
()
.peekable
();
let
mut
result
=
None
;
// Find the last modern mark from the end if it exists.
while
let
Some
(
&
mark
)
=
iter
.peek
()
{
if
mark
.transparency
()
==
Transparency
::
Opaque
{
while
let
Some
(
&
(
mark
,
transparency
)
)
=
iter
.peek
()
{
if
transparency
==
Transparency
::
Opaque
{
result
=
Some
(
mark
);
iter
.next
();
}
else
{
...
...
@@ -2005,8 +2005,8 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
}
}
// Then find the last legacy mark from the end if it exists.
for
mark
in
iter
{
if
mark
.transparency
()
==
Transparency
::
SemiTransparent
{
for
(
mark
,
transparency
)
in
iter
{
if
transparency
==
Transparency
::
SemiTransparent
{
result
=
Some
(
mark
);
}
else
{
break
;
...
...
src/librustc_resolve/macros.rs
浏览文件 @
94ef9f57
...
...
@@ -24,7 +24,7 @@
use
syntax
::
ext
::
base
::{
self
,
Annotatable
,
Determinacy
,
MultiModifier
,
MultiDecorator
};
use
syntax
::
ext
::
base
::{
MacroKind
,
SyntaxExtension
,
Resolver
as
SyntaxResolver
};
use
syntax
::
ext
::
expand
::{
self
,
AstFragment
,
AstFragmentKind
,
Invocation
,
InvocationKind
};
use
syntax
::
ext
::
hygiene
::{
self
,
Mark
,
Transparency
};
use
syntax
::
ext
::
hygiene
::{
self
,
Mark
};
use
syntax
::
ext
::
placeholders
::
placeholder
;
use
syntax
::
ext
::
tt
::
macro_rules
;
use
syntax
::
feature_gate
::{
self
,
emit_feature_err
,
GateIssue
};
...
...
@@ -331,13 +331,8 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
self
.unused_macros
.remove
(
&
def_id
);
let
ext
=
self
.get_macro
(
def
);
if
ext
.is_modern
()
{
let
transparency
=
if
ext
.is_transparent
()
{
Transparency
::
Transparent
}
else
{
Transparency
::
Opaque
};
invoc
.expansion_data.mark
.set_transparency
(
transparency
);
}
else
if
def_id
.krate
==
BUILTIN_MACROS_CRATE
{
invoc
.expansion_data.mark
.set_is_builtin
(
true
);
}
invoc
.expansion_data.mark
.set_default_transparency
(
ext
.default_transparency
());
invoc
.expansion_data.mark
.set_is_builtin
(
def_id
.krate
==
BUILTIN_MACROS_CRATE
);
Ok
(
Some
(
ext
))
}
...
...
src/libsyntax/ext/base.rs
浏览文件 @
94ef9f57
...
...
@@ -17,7 +17,7 @@
use
edition
::
Edition
;
use
errors
::{
DiagnosticBuilder
,
DiagnosticId
};
use
ext
::
expand
::{
self
,
AstFragment
,
Invocation
};
use
ext
::
hygiene
::{
self
,
Mark
,
SyntaxContext
};
use
ext
::
hygiene
::{
self
,
Mark
,
SyntaxContext
,
Transparency
};
use
fold
::{
self
,
Folder
};
use
parse
::{
self
,
parser
,
DirectoryOwnership
};
use
parse
::
token
;
...
...
@@ -673,20 +673,14 @@ pub fn kind(&self) -> MacroKind {
}
}
pub
fn
is_modern
(
&
self
)
->
bool
{
pub
fn
default_transparency
(
&
self
)
->
Transparency
{
match
*
self
{
SyntaxExtension
::
DeclMacro
{
..
}
|
SyntaxExtension
::
ProcMacro
{
..
}
|
SyntaxExtension
::
AttrProcMacro
(
..
)
|
SyntaxExtension
::
ProcMacroDerive
(
..
)
=>
true
,
_
=>
false
,
}
}
pub
fn
is_transparent
(
&
self
)
->
bool
{
match
*
self
{
SyntaxExtension
::
DeclMacro
{
is_transparent
,
..
}
=>
is_transparent
,
_
=>
false
,
SyntaxExtension
::
ProcMacroDerive
(
..
)
|
SyntaxExtension
::
DeclMacro
{
is_transparent
:
false
,
..
}
=>
Transparency
::
Opaque
,
SyntaxExtension
::
DeclMacro
{
is_transparent
:
true
,
..
}
=>
Transparency
::
Transparent
,
_
=>
Transparency
::
SemiTransparent
,
}
}
...
...
src/libsyntax_pos/hygiene.rs
浏览文件 @
94ef9f57
...
...
@@ -32,6 +32,7 @@
#[derive(Copy,
Clone,
Debug)]
struct
SyntaxContextData
{
outer_mark
:
Mark
,
transparency
:
Transparency
,
prev_ctxt
:
SyntaxContext
,
// This context, but with all transparent and semi-transparent marks filtered away.
opaque
:
SyntaxContext
,
...
...
@@ -46,14 +47,14 @@ struct SyntaxContextData {
#[derive(Clone,
Debug)]
struct
MarkData
{
parent
:
Mark
,
transparency
:
Transparency
,
default_
transparency
:
Transparency
,
is_builtin
:
bool
,
expn_info
:
Option
<
ExpnInfo
>
,
}
/// A property of a macro expansion that determines how identifiers
/// produced by that expansion are resolved.
#[derive(Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Debug)]
#[derive(Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Hash,
Debug)]
pub
enum
Transparency
{
/// Identifier produced by a transparent expansion is always resolved at call-site.
/// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
...
...
@@ -81,7 +82,7 @@ pub fn fresh(parent: Mark) -> Self {
Mark
::
fresh_with_data
(
MarkData
{
parent
,
// By default expansions behave like `macro_rules`.
transparency
:
Transparency
::
SemiTransparent
,
default_
transparency
:
Transparency
::
SemiTransparent
,
is_builtin
:
false
,
expn_info
:
None
,
},
data
)
...
...
@@ -127,9 +128,11 @@ pub fn set_expn_info(self, info: ExpnInfo) {
})
}
// FIXME: This operation doesn't really make sense when single macro expansion
// can produce tokens with different transparencies. Figure out how to avoid it.
pub
fn
modern
(
mut
self
)
->
Mark
{
HygieneData
::
with
(|
data
|
{
while
data
.marks
[
self
.0
as
usize
]
.transparency
!=
Transparency
::
Opaque
{
while
data
.marks
[
self
.0
as
usize
]
.
default_
transparency
!=
Transparency
::
Opaque
{
self
=
data
.marks
[
self
.0
as
usize
]
.parent
;
}
self
...
...
@@ -137,24 +140,20 @@ pub fn modern(mut self) -> Mark {
}
#[inline]
pub
fn
transparency
(
self
)
->
Transparency
{
assert_ne!
(
self
,
Mark
::
root
());
HygieneData
::
with
(|
data
|
data
.marks
[
self
.0
as
usize
]
.transparency
)
}
#[inline]
pub
fn
set_transparency
(
self
,
transparency
:
Transparency
)
{
pub
fn
set_default_transparency
(
self
,
transparency
:
Transparency
)
{
assert_ne!
(
self
,
Mark
::
root
());
HygieneData
::
with
(|
data
|
data
.marks
[
self
.0
as
usize
]
.transparency
=
transparency
)
HygieneData
::
with
(|
data
|
data
.marks
[
self
.0
as
usize
]
.
default_
transparency
=
transparency
)
}
#[inline]
pub
fn
is_builtin
(
self
)
->
bool
{
assert_ne!
(
self
,
Mark
::
root
());
HygieneData
::
with
(|
data
|
data
.marks
[
self
.0
as
usize
]
.is_builtin
)
}
#[inline]
pub
fn
set_is_builtin
(
self
,
is_builtin
:
bool
)
{
assert_ne!
(
self
,
Mark
::
root
());
HygieneData
::
with
(|
data
|
data
.marks
[
self
.0
as
usize
]
.is_builtin
=
is_builtin
)
}
...
...
@@ -201,7 +200,7 @@ pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
crate
struct
HygieneData
{
marks
:
Vec
<
MarkData
>
,
syntax_contexts
:
Vec
<
SyntaxContextData
>
,
markings
:
HashMap
<
(
SyntaxContext
,
Mark
),
SyntaxContext
>
,
markings
:
HashMap
<
(
SyntaxContext
,
Mark
,
Transparency
),
SyntaxContext
>
,
default_edition
:
Edition
,
}
...
...
@@ -212,12 +211,13 @@ impl HygieneData {
parent
:
Mark
::
root
(),
// If the root is opaque, then loops searching for an opaque mark
// will automatically stop after reaching it.
transparency
:
Transparency
::
Opaque
,
default_
transparency
:
Transparency
::
Opaque
,
is_builtin
:
true
,
expn_info
:
None
,
}],
syntax_contexts
:
vec!
[
SyntaxContextData
{
outer_mark
:
Mark
::
root
(),
transparency
:
Transparency
::
Opaque
,
prev_ctxt
:
SyntaxContext
(
0
),
opaque
:
SyntaxContext
(
0
),
opaque_and_semitransparent
:
SyntaxContext
(
0
),
...
...
@@ -267,7 +267,7 @@ pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
HygieneData
::
with
(|
data
|
{
data
.marks
.push
(
MarkData
{
parent
:
Mark
::
root
(),
transparency
:
Transparency
::
SemiTransparent
,
default_
transparency
:
Transparency
::
SemiTransparent
,
is_builtin
:
false
,
expn_info
:
Some
(
expansion_info
),
});
...
...
@@ -276,6 +276,7 @@ pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
data
.syntax_contexts
.push
(
SyntaxContextData
{
outer_mark
:
mark
,
transparency
:
Transparency
::
SemiTransparent
,
prev_ctxt
:
SyntaxContext
::
empty
(),
opaque
:
SyntaxContext
::
empty
(),
opaque_and_semitransparent
:
SyntaxContext
::
empty
(),
...
...
@@ -284,22 +285,31 @@ pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
})
}
/// Extend a syntax context with a given mark
pub
fn
apply_mark
(
self
,
mark
:
Mark
)
->
SyntaxContext
{
if
mark
.transparency
()
==
Transparency
::
Opaque
{
return
self
.apply_mark_internal
(
mark
);
assert_ne!
(
mark
,
Mark
::
root
());
self
.apply_mark_with_transparency
(
mark
,
HygieneData
::
with
(|
data
|
data
.marks
[
mark
.0
as
usize
]
.default_transparency
)
)
}
/// Extend a syntax context with a given mark and transparency
pub
fn
apply_mark_with_transparency
(
self
,
mark
:
Mark
,
transparency
:
Transparency
)
->
SyntaxContext
{
assert_ne!
(
mark
,
Mark
::
root
());
if
transparency
==
Transparency
::
Opaque
{
return
self
.apply_mark_internal
(
mark
,
transparency
);
}
let
call_site_ctxt
=
mark
.expn_info
()
.map_or
(
SyntaxContext
::
empty
(),
|
info
|
info
.call_site
.ctxt
());
let
call_site_ctxt
=
if
mark
.transparency
()
==
Transparency
::
SemiTransparent
{
let
call_site_ctxt
=
if
transparency
==
Transparency
::
SemiTransparent
{
call_site_ctxt
.modern
()
}
else
{
call_site_ctxt
.modern_and_legacy
()
};
if
call_site_ctxt
==
SyntaxContext
::
empty
()
{
return
self
.apply_mark_internal
(
mark
);
return
self
.apply_mark_internal
(
mark
,
transparency
);
}
// Otherwise, `mark` is a macros 1.0 definition and the call site is in a
...
...
@@ -312,27 +322,26 @@ pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
//
// See the example at `test/run-pass/hygiene/legacy_interaction.rs`.
let
mut
ctxt
=
call_site_ctxt
;
for
mark
in
self
.marks
()
{
ctxt
=
ctxt
.apply_mark_internal
(
mark
);
for
(
mark
,
transparency
)
in
self
.marks
()
{
ctxt
=
ctxt
.apply_mark_internal
(
mark
,
transparency
);
}
ctxt
.apply_mark_internal
(
mark
)
ctxt
.apply_mark_internal
(
mark
,
transparency
)
}
fn
apply_mark_internal
(
self
,
mark
:
Mark
)
->
SyntaxContext
{
fn
apply_mark_internal
(
self
,
mark
:
Mark
,
transparency
:
Transparency
)
->
SyntaxContext
{
HygieneData
::
with
(|
data
|
{
let
syntax_contexts
=
&
mut
data
.syntax_contexts
;
let
transparency
=
data
.marks
[
mark
.0
as
usize
]
.transparency
;
let
mut
opaque
=
syntax_contexts
[
self
.0
as
usize
]
.opaque
;
let
mut
opaque_and_semitransparent
=
syntax_contexts
[
self
.0
as
usize
]
.opaque_and_semitransparent
;
if
transparency
>=
Transparency
::
Opaque
{
let
prev_ctxt
=
opaque
;
opaque
=
*
data
.markings
.entry
((
prev_ctxt
,
mark
))
.or_insert_with
(||
{
opaque
=
*
data
.markings
.entry
((
prev_ctxt
,
mark
,
transparency
))
.or_insert_with
(||
{
let
new_opaque
=
SyntaxContext
(
syntax_contexts
.len
()
as
u32
);
syntax_contexts
.push
(
SyntaxContextData
{
outer_mark
:
mark
,
transparency
,
prev_ctxt
,
opaque
:
new_opaque
,
opaque_and_semitransparent
:
new_opaque
,
...
...
@@ -344,11 +353,12 @@ fn apply_mark_internal(self, mark: Mark) -> SyntaxContext {
if
transparency
>=
Transparency
::
SemiTransparent
{
let
prev_ctxt
=
opaque_and_semitransparent
;
opaque_and_semitransparent
=
*
data
.markings
.entry
((
prev_ctxt
,
mark
))
.or_insert_with
(||
{
*
data
.markings
.entry
((
prev_ctxt
,
mark
,
transparency
))
.or_insert_with
(||
{
let
new_opaque_and_semitransparent
=
SyntaxContext
(
syntax_contexts
.len
()
as
u32
);
syntax_contexts
.push
(
SyntaxContextData
{
outer_mark
:
mark
,
transparency
,
prev_ctxt
,
opaque
,
opaque_and_semitransparent
:
new_opaque_and_semitransparent
,
...
...
@@ -358,11 +368,12 @@ fn apply_mark_internal(self, mark: Mark) -> SyntaxContext {
}
let
prev_ctxt
=
self
;
*
data
.markings
.entry
((
prev_ctxt
,
mark
))
.or_insert_with
(||
{
*
data
.markings
.entry
((
prev_ctxt
,
mark
,
transparency
))
.or_insert_with
(||
{
let
new_opaque_and_semitransparent_and_transparent
=
SyntaxContext
(
syntax_contexts
.len
()
as
u32
);
syntax_contexts
.push
(
SyntaxContextData
{
outer_mark
:
mark
,
transparency
,
prev_ctxt
,
opaque
,
opaque_and_semitransparent
,
...
...
@@ -396,12 +407,13 @@ pub fn remove_mark(&mut self) -> Mark {
})
}
pub
fn
marks
(
mut
self
)
->
Vec
<
Mark
>
{
pub
fn
marks
(
mut
self
)
->
Vec
<
(
Mark
,
Transparency
)
>
{
HygieneData
::
with
(|
data
|
{
let
mut
marks
=
Vec
::
new
();
while
self
!=
SyntaxContext
::
empty
()
{
marks
.push
(
data
.syntax_contexts
[
self
.0
as
usize
]
.outer_mark
);
self
=
data
.syntax_contexts
[
self
.0
as
usize
]
.prev_ctxt
;
let
ctxt_data
=
&
data
.syntax_contexts
[
self
.0
as
usize
];
marks
.push
((
ctxt_data
.outer_mark
,
ctxt_data
.transparency
));
self
=
ctxt_data
.prev_ctxt
;
}
marks
.reverse
();
marks
...
...
src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs
0 → 100644
浏览文件 @
94ef9f57
// Copyright 2016 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.
// run-pass
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type
=
"proc-macro"
]
extern
crate
proc_macro
;
use
proc_macro
::
*
;
#[proc_macro]
pub
fn
check
(
_
:
TokenStream
)
->
TokenStream
{
"
struct Outer;
mod inner {
type Inner = Outer; // `Outer` shouldn't be available from here
}
"
.parse
()
.unwrap
()
}
src/test/ui-fulldeps/proc-macro/generate-mod.rs
0 → 100644
浏览文件 @
94ef9f57
// Copyright 2018 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.
// Modules generated by transparent proc macros still acts as barriers for names (issue #50504).
// aux-build:generate-mod.rs
#![feature(proc_macro,
proc_macro_gen)]
extern
crate
generate_mod
;
generate_mod
::
check!
();
//~ ERROR cannot find type `Outer` in this scope
fn
main
()
{}
src/test/ui-fulldeps/proc-macro/generate-mod.stderr
0 → 100644
浏览文件 @
94ef9f57
error[E0412]: cannot find type `Outer` in this scope
--> $DIR/generate-mod.rs:19:1
|
LL | generate_mod::check!(); //~ ERROR cannot find type `Outer` in this scope
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0412`.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录