Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
fbf1bec4
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,发现更多精彩内容 >>
提交
fbf1bec4
编写于
3月 08, 2021
作者:
V
Vadim Petrochenkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
resolve/expand: Cache intermediate results of `#[derive]` expansion
上级
b1ea2618
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
97 addition
and
73 deletion
+97
-73
compiler/rustc_builtin_macros/src/derive.rs
compiler/rustc_builtin_macros/src/derive.rs
+32
-25
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/base.rs
+4
-5
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/expand.rs
+1
-1
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/lib.rs
+11
-4
compiler/rustc_resolve/src/macros.rs
compiler/rustc_resolve/src/macros.rs
+49
-38
未找到文件。
compiler/rustc_builtin_macros/src/derive.rs
浏览文件 @
fbf1bec4
use
crate
::
cfg_eval
::
cfg_eval
;
use
rustc_ast
::{
self
as
ast
,
token
,
ItemKind
,
MetaItemKind
,
NestedMetaItem
,
StmtKind
};
use
rustc_ast
::{
self
as
ast
,
attr
,
token
,
ItemKind
,
MetaItemKind
,
NestedMetaItem
,
StmtKind
};
use
rustc_errors
::{
struct_span_err
,
Applicability
};
use
rustc_expand
::
base
::{
Annotatable
,
ExpandResult
,
ExtCtxt
,
Indeterminate
,
MultiItemModifier
};
use
rustc_feature
::
AttributeTemplate
;
...
...
@@ -26,32 +26,39 @@ fn expand(
return
ExpandResult
::
Ready
(
vec!
[
item
]);
}
let
template
=
AttributeTemplate
{
list
:
Some
(
"Trait1, Trait2, ..."
),
..
Default
::
default
()
};
let
attr
=
ecx
.attribute
(
meta_item
.clone
());
validate_attr
::
check_builtin_attribute
(
&
sess
.parse_sess
,
&
attr
,
sym
::
derive
,
template
);
let
result
=
ecx
.resolver
.resolve_derives
(
ecx
.current_expansion.id
,
ecx
.force_mode
,
&
||
{
let
template
=
AttributeTemplate
{
list
:
Some
(
"Trait1, Trait2, ..."
),
..
Default
::
default
()
};
let
attr
=
attr
::
mk_attr_outer
(
meta_item
.clone
());
validate_attr
::
check_builtin_attribute
(
&
sess
.parse_sess
,
&
attr
,
sym
::
derive
,
template
,
);
let
derives
:
Vec
<
_
>
=
attr
.meta_item_list
()
.unwrap_or_default
()
.into_iter
()
.filter_map
(|
nested_meta
|
match
nested_meta
{
NestedMetaItem
::
MetaItem
(
meta
)
=>
Some
(
meta
),
NestedMetaItem
::
Literal
(
lit
)
=>
{
// Reject `#[derive("Debug")]`.
report_unexpected_literal
(
sess
,
&
lit
);
None
}
})
.map
(|
meta
|
{
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
report_path_args
(
sess
,
&
meta
);
meta
.path
})
.collect
();
attr
.meta_item_list
()
.unwrap_or_default
()
.into_iter
()
.filter_map
(|
nested_meta
|
match
nested_meta
{
NestedMetaItem
::
MetaItem
(
meta
)
=>
Some
(
meta
),
NestedMetaItem
::
Literal
(
lit
)
=>
{
// Reject `#[derive("Debug")]`.
report_unexpected_literal
(
sess
,
&
lit
);
None
}
})
.map
(|
meta
|
{
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
report_path_args
(
sess
,
&
meta
);
meta
.path
})
.map
(|
path
|
(
path
,
None
))
.collect
()
});
// FIXME: Try to cache intermediate results to avoid collecting same paths multiple times.
match
ecx
.resolver
.resolve_derives
(
ecx
.current_expansion.id
,
derives
,
ecx
.force_mode
)
{
match
result
{
Ok
(())
=>
ExpandResult
::
Ready
(
cfg_eval
(
ecx
,
item
)),
Err
(
Indeterminate
)
=>
ExpandResult
::
Retry
(
item
),
}
...
...
compiler/rustc_expand/src/base.rs
浏览文件 @
fbf1bec4
...
...
@@ -868,6 +868,8 @@ pub fn expn_data(
/// Error type that denotes indeterminacy.
pub
struct
Indeterminate
;
pub
type
DeriveResolutions
=
Vec
<
(
ast
::
Path
,
Option
<
Lrc
<
SyntaxExtension
>>
)
>
;
pub
trait
ResolverExpand
{
fn
next_node_id
(
&
mut
self
)
->
NodeId
;
...
...
@@ -904,15 +906,12 @@ fn resolve_macro_invocation(
fn
resolve_derives
(
&
mut
self
,
expn_id
:
ExpnId
,
derives
:
Vec
<
ast
::
Path
>
,
force
:
bool
,
derive_paths
:
&
dyn
Fn
()
->
DeriveResolutions
,
)
->
Result
<
(),
Indeterminate
>
;
/// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
/// back from resolver.
fn
take_derive_resolutions
(
&
mut
self
,
expn_id
:
ExpnId
,
)
->
Option
<
Vec
<
(
Lrc
<
SyntaxExtension
>
,
ast
::
Path
)
>>
;
fn
take_derive_resolutions
(
&
mut
self
,
expn_id
:
ExpnId
)
->
Option
<
DeriveResolutions
>
;
/// Path resolution logic for `#[cfg_accessible(path)]`.
fn
cfg_accessible
(
&
mut
self
,
expn_id
:
ExpnId
,
path
:
&
ast
::
Path
)
->
Result
<
bool
,
Indeterminate
>
;
}
...
...
compiler/rustc_expand/src/expand.rs
浏览文件 @
fbf1bec4
...
...
@@ -515,7 +515,7 @@ enum AnnotatableRef<'a> {
invocations
.reserve
(
derives
.len
());
derives
.into_iter
()
.map
(|(
_
exts
,
path
)|
{
.map
(|(
path
,
_
exts
)|
{
// FIXME: Consider using the derive resolutions (`_exts`)
// instead of enqueuing the derives to be resolved again later.
let
expn_id
=
ExpnId
::
fresh
(
None
);
...
...
compiler/rustc_resolve/src/lib.rs
浏览文件 @
fbf1bec4
...
...
@@ -37,7 +37,7 @@
use
rustc_data_structures
::
ptr_key
::
PtrKey
;
use
rustc_data_structures
::
sync
::
Lrc
;
use
rustc_errors
::{
struct_span_err
,
Applicability
,
DiagnosticBuilder
};
use
rustc_expand
::
base
::{
SyntaxExtension
,
SyntaxExtensionKind
};
use
rustc_expand
::
base
::{
DeriveResolutions
,
SyntaxExtension
,
SyntaxExtensionKind
};
use
rustc_hir
::
def
::
Namespace
::
*
;
use
rustc_hir
::
def
::{
self
,
CtorOf
,
DefKind
,
NonMacroAttrKind
,
PartialRes
};
use
rustc_hir
::
def_id
::{
CrateNum
,
DefId
,
DefIdMap
,
LocalDefId
,
CRATE_DEF_INDEX
};
...
...
@@ -851,6 +851,12 @@ enum BuiltinMacroState {
AlreadySeen
(
Span
),
}
struct
DeriveData
{
resolutions
:
DeriveResolutions
,
helper_attrs
:
Vec
<
Ident
>
,
has_derive_copy
:
bool
,
}
/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
...
...
@@ -973,8 +979,9 @@ pub struct Resolver<'a> {
output_macro_rules_scopes
:
FxHashMap
<
ExpnId
,
MacroRulesScopeRef
<
'a
>>
,
/// Helper attributes that are in scope for the given expansion.
helper_attrs
:
FxHashMap
<
ExpnId
,
Vec
<
Ident
>>
,
/// Resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`.
derive_resolutions
:
FxHashMap
<
ExpnId
,
Vec
<
(
Lrc
<
SyntaxExtension
>
,
ast
::
Path
)
>>
,
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
/// with the given `ExpnId`.
derive_data
:
FxHashMap
<
ExpnId
,
DeriveData
>
,
/// Avoid duplicated errors for "name already defined".
name_already_seen
:
FxHashMap
<
Symbol
,
Span
>
,
...
...
@@ -1310,7 +1317,7 @@ pub fn new(
invocation_parent_scopes
:
Default
::
default
(),
output_macro_rules_scopes
:
Default
::
default
(),
helper_attrs
:
Default
::
default
(),
derive_
resolutions
:
Default
::
default
(),
derive_
data
:
Default
::
default
(),
local_macro_def_scopes
:
FxHashMap
::
default
(),
name_already_seen
:
FxHashMap
::
default
(),
potentially_unused_imports
:
Vec
::
new
(),
...
...
compiler/rustc_resolve/src/macros.rs
浏览文件 @
fbf1bec4
...
...
@@ -4,7 +4,7 @@
use
crate
::
imports
::
ImportResolver
;
use
crate
::
Namespace
::
*
;
use
crate
::{
AmbiguityError
,
AmbiguityErrorMisc
,
AmbiguityKind
,
BuiltinMacroState
,
Determinacy
};
use
crate
::{
CrateLint
,
ParentScope
,
ResolutionError
,
Resolver
,
Scope
,
ScopeSet
,
Weak
};
use
crate
::{
CrateLint
,
DeriveData
,
ParentScope
,
ResolutionError
,
Resolver
,
Scope
,
ScopeSet
,
Weak
};
use
crate
::{
ModuleKind
,
ModuleOrUniformRoot
,
NameBinding
,
PathResult
,
Segment
,
ToNameBinding
};
use
rustc_ast
::{
self
as
ast
,
Inline
,
ItemKind
,
ModKind
,
NodeId
};
use
rustc_ast_lowering
::
ResolverAstLowering
;
...
...
@@ -14,8 +14,8 @@
use
rustc_data_structures
::
ptr_key
::
PtrKey
;
use
rustc_data_structures
::
sync
::
Lrc
;
use
rustc_errors
::
struct_span_err
;
use
rustc_expand
::
base
::
Annotatable
;
use
rustc_expand
::
base
::{
Indeterminate
,
ResolverExpand
,
SyntaxExtension
,
SyntaxExtensionKind
};
use
rustc_expand
::
base
::
{
Annotatable
,
DeriveResolutions
,
Indeterminate
,
ResolverExpand
}
;
use
rustc_expand
::
base
::{
SyntaxExtension
,
SyntaxExtensionKind
};
use
rustc_expand
::
compile_declarative_macro
;
use
rustc_expand
::
expand
::{
AstFragment
,
Invocation
,
InvocationKind
,
SupportsMacroExpansion
};
use
rustc_feature
::
is_builtin_attr_name
;
...
...
@@ -359,8 +359,8 @@ fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
fn
resolve_derives
(
&
mut
self
,
expn_id
:
ExpnId
,
derives
:
Vec
<
ast
::
Path
>
,
force
:
bool
,
derive_paths
:
&
dyn
Fn
()
->
DeriveResolutions
,
)
->
Result
<
(),
Indeterminate
>
{
// Block expansion of the container until we resolve all derives in it.
// This is required for two reasons:
...
...
@@ -368,49 +368,60 @@ fn resolve_derives(
// is applied, so they have to be produced by the container's expansion rather
// than by individual derives.
// - Derives in the container need to know whether one of them is a built-in `Copy`.
// FIXME: Try to cache intermediate results to avoid resolving same derives multiple times.
// Temporarily take the data to avoid borrow checker conflicts.
let
mut
derive_data
=
mem
::
take
(
&
mut
self
.derive_data
);
let
entry
=
derive_data
.entry
(
expn_id
)
.or_insert_with
(||
DeriveData
{
resolutions
:
derive_paths
(),
helper_attrs
:
Vec
::
new
(),
has_derive_copy
:
false
,
});
let
parent_scope
=
self
.invocation_parent_scopes
[
&
expn_id
];
let
mut
exts
=
Vec
::
new
();
let
mut
helper_attrs
=
Vec
::
new
();
let
mut
has_derive_copy
=
false
;
for
path
in
derives
{
exts
.push
((
match
self
.resolve_macro_path
(
&
path
,
Some
(
MacroKind
::
Derive
),
&
parent_scope
,
true
,
force
,
)
{
Ok
((
Some
(
ext
),
_
))
=>
{
let
span
=
path
.segments
.last
()
.unwrap
()
.ident.span
.normalize_to_macros_2_0
();
helper_attrs
.extend
(
ext
.helper_attrs
.iter
()
.map
(|
name
|
Ident
::
new
(
*
name
,
span
)));
has_derive_copy
|
=
ext
.builtin_name
==
Some
(
sym
::
Copy
);
ext
}
Ok
(
_
)
|
Err
(
Determinacy
::
Determined
)
=>
self
.dummy_ext
(
MacroKind
::
Derive
),
Err
(
Determinacy
::
Undetermined
)
=>
return
Err
(
Indeterminate
),
},
path
,
))
for
(
path
,
opt_ext
)
in
&
mut
entry
.resolutions
{
if
opt_ext
.is_none
()
{
*
opt_ext
=
Some
(
match
self
.resolve_macro_path
(
&
path
,
Some
(
MacroKind
::
Derive
),
&
parent_scope
,
true
,
force
,
)
{
Ok
((
Some
(
ext
),
_
))
=>
{
if
!
ext
.helper_attrs
.is_empty
()
{
let
last_seg
=
path
.segments
.last
()
.unwrap
();
let
span
=
last_seg
.ident.span
.normalize_to_macros_2_0
();
entry
.helper_attrs
.extend
(
ext
.helper_attrs
.iter
()
.map
(|
name
|
Ident
::
new
(
*
name
,
span
)),
);
}
entry
.has_derive_copy
|
=
ext
.builtin_name
==
Some
(
sym
::
Copy
);
ext
}
Ok
(
_
)
|
Err
(
Determinacy
::
Determined
)
=>
self
.dummy_ext
(
MacroKind
::
Derive
),
Err
(
Determinacy
::
Undetermined
)
=>
{
assert
!
(
self
.derive_data
.is_empty
());
self
.derive_data
=
derive_data
;
return
Err
(
Indeterminate
);
}
},
);
}
}
self
.derive_resolutions
.insert
(
expn_id
,
exts
);
self
.helper_attrs
.insert
(
expn_id
,
helper_attrs
);
// If we get to here, then `derive_data` for the given `expn_id` will only be accessed by
// `take_derive_resolutions` later, so we can steal `helper_attrs` instead of cloning them.
self
.helper_attrs
.insert
(
expn_id
,
mem
::
take
(
&
mut
entry
.helper_attrs
));
// Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive
// has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`.
if
has_derive_copy
||
self
.has_derive_copy
(
parent_scope
.expansion
)
{
if
entry
.
has_derive_copy
||
self
.has_derive_copy
(
parent_scope
.expansion
)
{
self
.containers_deriving_copy
.insert
(
expn_id
);
}
assert
!
(
self
.derive_data
.is_empty
());
self
.derive_data
=
derive_data
;
Ok
(())
}
fn
take_derive_resolutions
(
&
mut
self
,
expn_id
:
ExpnId
,
)
->
Option
<
Vec
<
(
Lrc
<
SyntaxExtension
>
,
ast
::
Path
)
>>
{
self
.derive_resolutions
.remove
(
&
expn_id
)
fn
take_derive_resolutions
(
&
mut
self
,
expn_id
:
ExpnId
)
->
Option
<
DeriveResolutions
>
{
self
.derive_data
.remove
(
&
expn_id
)
.map
(|
data
|
data
.resolutions
)
}
// The function that implements the resolution logic of `#[cfg_accessible(path)]`.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录