Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
b09de95f
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
b09de95f
编写于
10月 16, 2021
作者:
C
Camille GILLOT
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merge two query callbacks arrays.
上级
dc714336
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
180 addition
and
247 deletion
+180
-247
compiler/rustc_incremental/src/assert_dep_graph.rs
compiler/rustc_incremental/src/assert_dep_graph.rs
+23
-17
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
+6
-15
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/passes.rs
+1
-0
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
+72
-114
compiler/rustc_middle/src/dep_graph/mod.rs
compiler/rustc_middle/src/dep_graph/mod.rs
+11
-11
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/context.rs
+8
-1
compiler/rustc_query_impl/src/lib.rs
compiler/rustc_query_impl/src/lib.rs
+1
-2
compiler/rustc_query_impl/src/plumbing.rs
compiler/rustc_query_impl/src/plumbing.rs
+33
-65
compiler/rustc_query_system/src/dep_graph/dep_node.rs
compiler/rustc_query_system/src/dep_graph/dep_node.rs
+6
-3
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
+5
-5
compiler/rustc_query_system/src/dep_graph/mod.rs
compiler/rustc_query_system/src/dep_graph/mod.rs
+5
-5
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_query_system/src/query/plumbing.rs
+9
-9
未找到文件。
compiler/rustc_incremental/src/assert_dep_graph.rs
浏览文件 @
b09de95f
...
...
@@ -126,30 +126,36 @@ fn process_attrs(&mut self, hir_id: hir::HirId) {
if
attr
.has_name
(
sym
::
rustc_if_this_changed
)
{
let
dep_node_interned
=
self
.argument
(
attr
);
let
dep_node
=
match
dep_node_interned
{
None
=>
DepNode
::
from_def_path_hash
(
def_path_hash
,
DepKind
::
hir_owner
),
Some
(
n
)
=>
match
DepNode
::
from_label_string
(
&
n
.as_str
(),
def_path_hash
)
{
Ok
(
n
)
=>
n
,
Err
(())
=>
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
&
format!
(
"unrecognized DepNode variant {:?}"
,
n
),
);
None
=>
{
DepNode
::
from_def_path_hash
(
self
.tcx
,
def_path_hash
,
DepKind
::
hir_owner
)
}
Some
(
n
)
=>
{
match
DepNode
::
from_label_string
(
self
.tcx
,
&
n
.as_str
(),
def_path_hash
)
{
Ok
(
n
)
=>
n
,
Err
(())
=>
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
&
format!
(
"unrecognized DepNode variant {:?}"
,
n
),
);
}
}
}
,
}
};
self
.if_this_changed
.push
((
attr
.span
,
def_id
.to_def_id
(),
dep_node
));
}
else
if
attr
.has_name
(
sym
::
rustc_then_this_would_need
)
{
let
dep_node_interned
=
self
.argument
(
attr
);
let
dep_node
=
match
dep_node_interned
{
Some
(
n
)
=>
match
DepNode
::
from_label_string
(
&
n
.as_str
(),
def_path_hash
)
{
Ok
(
n
)
=>
n
,
Err
(())
=>
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
&
format!
(
"unrecognized DepNode variant {:?}"
,
n
),
);
Some
(
n
)
=>
{
match
DepNode
::
from_label_string
(
self
.tcx
,
&
n
.as_str
(),
def_path_hash
)
{
Ok
(
n
)
=>
n
,
Err
(())
=>
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
&
format!
(
"unrecognized DepNode variant {:?}"
,
n
),
);
}
}
}
,
}
None
=>
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
"missing DepNode variant"
);
}
...
...
compiler/rustc_incremental/src/persist/dirty_clean.rs
浏览文件 @
b09de95f
...
...
@@ -15,7 +15,7 @@
use
rustc_ast
::{
self
as
ast
,
Attribute
,
NestedMetaItem
};
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_hir
as
hir
;
use
rustc_hir
::
def_id
::
{
DefId
,
LocalDefId
}
;
use
rustc_hir
::
def_id
::
LocalDefId
;
use
rustc_hir
::
intravisit
;
use
rustc_hir
::
itemlikevisit
::
ItemLikeVisitor
;
use
rustc_hir
::
Node
as
HirNode
;
...
...
@@ -302,18 +302,6 @@ fn resolve_labels(&self, item: &NestedMetaItem, value: Symbol) -> Labels {
out
}
fn
dep_nodes
<
'l
>
(
&
self
,
labels
:
&
'l
Labels
,
def_id
:
DefId
,
)
->
impl
Iterator
<
Item
=
DepNode
>
+
'l
{
let
def_path_hash
=
self
.tcx
.def_path_hash
(
def_id
);
labels
.iter
()
.map
(
move
|
label
|
match
DepNode
::
from_label_string
(
label
,
def_path_hash
)
{
Ok
(
dep_node
)
=>
dep_node
,
Err
(())
=>
unreachable!
(
"label: {}"
,
label
),
})
}
fn
dep_node_str
(
&
self
,
dep_node
:
&
DepNode
)
->
String
{
if
let
Some
(
def_id
)
=
dep_node
.extract_def_id
(
self
.tcx
)
{
format!
(
"{:?}({})"
,
dep_node
.kind
,
self
.tcx
.def_path_str
(
def_id
))
...
...
@@ -345,16 +333,19 @@ fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
}
fn
check_item
(
&
mut
self
,
item_id
:
LocalDefId
,
item_span
:
Span
)
{
let
def_path_hash
=
self
.tcx
.def_path_hash
(
item_id
.to_def_id
());
for
attr
in
self
.tcx
.get_attrs
(
item_id
.to_def_id
())
.iter
()
{
let
assertion
=
match
self
.assertion_maybe
(
item_id
,
attr
)
{
Some
(
a
)
=>
a
,
None
=>
continue
,
};
self
.checked_attrs
.insert
(
attr
.id
);
for
dep_node
in
self
.dep_nodes
(
&
assertion
.clean
,
item_id
.to_def_id
())
{
for
label
in
assertion
.clean
{
let
dep_node
=
DepNode
::
from_label_string
(
self
.tcx
,
&
label
,
def_path_hash
)
.unwrap
();
self
.assert_clean
(
item_span
,
dep_node
);
}
for
dep_node
in
self
.dep_nodes
(
&
assertion
.dirty
,
item_id
.to_def_id
())
{
for
label
in
assertion
.dirty
{
let
dep_node
=
DepNode
::
from_label_string
(
self
.tcx
,
&
label
,
def_path_hash
)
.unwrap
();
self
.assert_dirty
(
item_span
,
dep_node
);
}
}
...
...
compiler/rustc_interface/src/passes.rs
浏览文件 @
b09de95f
...
...
@@ -838,6 +838,7 @@ pub fn create_global_ctxt<'tcx>(
dep_graph
,
queries
.on_disk_cache
.as_ref
()
.map
(
OnDiskCache
::
as_dyn
),
queries
.as_dyn
(),
&
rustc_query_impl
::
QUERY_CALLBACKS
,
crate_name
,
outputs
,
)
...
...
compiler/rustc_middle/src/dep_graph/dep_node.rs
浏览文件 @
b09de95f
...
...
@@ -78,32 +78,70 @@ pub struct DepKindStruct {
/// Anonymous queries cannot be replayed from one compiler invocation to the next.
/// When their result is needed, it is recomputed. They are useful for fine-grained
/// dependency tracking, and caching within one compiler invocation.
pub
(
super
)
is_anon
:
bool
,
pub
is_anon
:
bool
,
/// Eval-always queries do not track their dependencies, and are always recomputed, even if
/// their inputs have not changed since the last compiler invocation. The result is still
/// cached within one compiler invocation.
pub
(
super
)
is_eval_always
:
bool
,
pub
is_eval_always
:
bool
,
/// Whether the query key can be recovered from the hashed fingerprint.
/// See [DepNodeParams] trait for the behaviour of each key type.
// FIXME: Make this a simple boolean once DepNodeParams::fingerprint_style
// can be made a specialized associated const.
fingerprint_style
:
fn
()
->
FingerprintStyle
,
}
impl
std
::
ops
::
Deref
for
DepKind
{
type
Target
=
DepKindStruct
;
fn
deref
(
&
self
)
->
&
DepKindStruct
{
&
DEP_KINDS
[
*
self
as
usize
]
}
pub
fingerprint_style
:
fn
()
->
FingerprintStyle
,
/// The red/green evaluation system will try to mark a specific DepNode in the
/// dependency graph as green by recursively trying to mark the dependencies of
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
/// where we don't know if it is red or green and we therefore actually have
/// to recompute its value in order to find out. Since the only piece of
/// information that we have at that point is the `DepNode` we are trying to
/// re-evaluate, we need some way to re-run a query from just that. This is what
/// `force_from_dep_node()` implements.
///
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
/// is usually constructed by computing a stable hash of the query-key that the
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
/// back from hash to query-key (since hash functions are not reversible). For
/// this reason `force_from_dep_node()` is expected to fail from time to time
/// because we just cannot find out, from the `DepNode` alone, what the
/// corresponding query-key is and therefore cannot re-run the query.
///
/// The system deals with this case letting `try_mark_green` fail which forces
/// the root query to be re-evaluated.
///
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
/// Fortunately, we can use some contextual information that will allow us to
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
/// valid `DefPathHash`. Since we also always build a huge table that maps every
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
/// everything we need to re-run the query.
///
/// Take the `mir_promoted` query as an example. Like many other queries, it
/// just has a single parameter: the `DefId` of the item it will compute the
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
/// `DefId` in `tcx.def_path_hash_to_def_id`.
///
/// When you implement a new query, it will likely have a corresponding new
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
/// add it to the "We don't have enough information to reconstruct..." group in
/// the match below.
pub
force_from_dep_node
:
fn
(
tcx
:
TyCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
->
bool
,
/// Invoke a query to put the on-disk cached value in memory.
pub
try_load_from_on_disk_cache
:
fn
(
TyCtxt
<
'_
>
,
&
DepNode
),
}
impl
DepKind
{
#[inline(always)]
pub
fn
fingerprint_style
(
&
self
)
->
FingerprintStyle
{
pub
fn
fingerprint_style
(
self
,
tcx
:
TyCtxt
<
'_
>
)
->
FingerprintStyle
{
// Only fetch the DepKindStruct once.
let
data
:
&
DepKindStruct
=
&**
self
;
let
data
=
tcx
.query_kind
(
self
)
;
if
data
.is_anon
{
return
FingerprintStyle
::
Opaque
;
}
...
...
@@ -112,94 +150,6 @@ pub fn fingerprint_style(&self) -> FingerprintStyle {
}
}
macro_rules!
is_anon_attr
{
(
anon
)
=>
{
true
};
(
$attr:ident
)
=>
{
false
};
}
macro_rules!
is_eval_always_attr
{
(
eval_always
)
=>
{
true
};
(
$attr:ident
)
=>
{
false
};
}
macro_rules!
contains_anon_attr
{
(
$
((
$attr:ident
$
(
$attr_args:tt
)
*
)),
*
)
=>
({
$
(
is_anon_attr!
(
$attr
)
|
)
*
false
});
}
macro_rules!
contains_eval_always_attr
{
(
$
((
$attr:ident
$
(
$attr_args:tt
)
*
)),
*
)
=>
({
$
(
is_eval_always_attr!
(
$attr
)
|
)
*
false
});
}
#[allow(non_upper_case_globals)]
pub
mod
dep_kind
{
use
super
::
*
;
use
crate
::
ty
::
query
::
query_keys
;
use
rustc_query_system
::
dep_graph
::
FingerprintStyle
;
// We use this for most things when incr. comp. is turned off.
pub
const
Null
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Unit
,
};
pub
const
TraitSelect
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
true
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Unit
,
};
pub
const
CompileCodegenUnit
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Opaque
,
};
pub
const
CompileMonoItem
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Opaque
,
};
macro_rules!
define_query_dep_kinds
{
(
$
(
[
$
(
$attrs:tt
)
*
]
$variant:ident
$
((
$tuple_arg_ty:ty
$
(,)
?
))
*
,)
*
)
=>
(
$
(
pub
const
$variant
:
DepKindStruct
=
{
const
is_anon
:
bool
=
contains_anon_attr!
(
$
(
$attrs
)
*
);
const
is_eval_always
:
bool
=
contains_eval_always_attr!
(
$
(
$attrs
)
*
);
#[inline(always)]
fn
fingerprint_style
()
->
rustc_query_system
::
dep_graph
::
FingerprintStyle
{
<
query_keys
::
$variant
<
'_
>
as
DepNodeParams
<
TyCtxt
<
'_
>>>
::
fingerprint_style
()
}
DepKindStruct
{
is_anon
,
is_eval_always
,
fingerprint_style
,
}
};)
*
);
}
rustc_dep_node_append!
([
define_query_dep_kinds!
][]);
}
macro_rules!
define_dep_nodes
{
(
<
$tcx:tt
>
$
(
...
...
@@ -212,9 +162,7 @@ fn fingerprint_style() -> rustc_query_system::dep_graph::FingerprintStyle {
(
$mod:ident
)
=>
{[
$
((
$mod
::
$variant
),)
*
]};
}
static
DEP_KINDS
:
&
[
DepKindStruct
]
=
&
make_dep_kind_array!
(
dep_kind
);
/// This enum serves as an index into the `DEP_KINDS` array.
/// This enum serves as an index into arrays built by `make_dep_kind_array`.
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Encodable,
Decodable)]
#[allow(non_camel_case_types)]
pub
enum
DepKind
{
...
...
@@ -280,7 +228,7 @@ pub trait DepNodeExt: Sized {
/// Construct a DepNode from the given DepKind and DefPathHash. This
/// method will assert that the given DepKind actually requires a
/// single DefId/DefPathHash parameter.
fn
from_def_path_hash
(
def_path_hash
:
DefPathHash
,
kind
:
DepKind
)
->
Self
;
fn
from_def_path_hash
(
tcx
:
TyCtxt
<
'_
>
,
def_path_hash
:
DefPathHash
,
kind
:
DepKind
)
->
Self
;
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
...
...
@@ -295,7 +243,11 @@ pub trait DepNodeExt: Sized {
fn
extract_def_id
(
&
self
,
tcx
:
TyCtxt
<
'_
>
)
->
Option
<
DefId
>
;
/// Used in testing
fn
from_label_string
(
label
:
&
str
,
def_path_hash
:
DefPathHash
)
->
Result
<
Self
,
()
>
;
fn
from_label_string
(
tcx
:
TyCtxt
<
'_
>
,
label
:
&
str
,
def_path_hash
:
DefPathHash
,
)
->
Result
<
Self
,
()
>
;
/// Used in testing
fn
has_label_string
(
label
:
&
str
)
->
bool
;
...
...
@@ -305,8 +257,8 @@ impl DepNodeExt for DepNode {
/// Construct a DepNode from the given DepKind and DefPathHash. This
/// method will assert that the given DepKind actually requires a
/// single DefId/DefPathHash parameter.
fn
from_def_path_hash
(
def_path_hash
:
DefPathHash
,
kind
:
DepKind
)
->
DepNode
{
debug_assert!
(
kind
.fingerprint_style
()
==
FingerprintStyle
::
DefPathHash
);
fn
from_def_path_hash
(
tcx
:
TyCtxt
<
'_
>
,
def_path_hash
:
DefPathHash
,
kind
:
DepKind
)
->
DepNode
{
debug_assert!
(
kind
.fingerprint_style
(
tcx
)
==
FingerprintStyle
::
DefPathHash
);
DepNode
{
kind
,
hash
:
def_path_hash
.0
.into
()
}
}
...
...
@@ -321,7 +273,7 @@ fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
/// refers to something from the previous compilation session that
/// has been removed.
fn
extract_def_id
(
&
self
,
tcx
:
TyCtxt
<
'tcx
>
)
->
Option
<
DefId
>
{
if
self
.kind
.fingerprint_style
()
==
FingerprintStyle
::
DefPathHash
{
if
self
.kind
.fingerprint_style
(
tcx
)
==
FingerprintStyle
::
DefPathHash
{
Some
(
tcx
.def_path_hash_to_def_id
(
DefPathHash
(
self
.hash
.into
())))
}
else
{
None
...
...
@@ -329,13 +281,19 @@ fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
}
/// Used in testing
fn
from_label_string
(
label
:
&
str
,
def_path_hash
:
DefPathHash
)
->
Result
<
DepNode
,
()
>
{
fn
from_label_string
(
tcx
:
TyCtxt
<
'_
>
,
label
:
&
str
,
def_path_hash
:
DefPathHash
,
)
->
Result
<
DepNode
,
()
>
{
let
kind
=
dep_kind_from_label_string
(
label
)
?
;
match
kind
.fingerprint_style
()
{
match
kind
.fingerprint_style
(
tcx
)
{
FingerprintStyle
::
Opaque
=>
Err
(()),
FingerprintStyle
::
Unit
=>
Ok
(
DepNode
::
new_no_params
(
kind
)),
FingerprintStyle
::
DefPathHash
=>
Ok
(
DepNode
::
from_def_path_hash
(
def_path_hash
,
kind
)),
FingerprintStyle
::
Unit
=>
Ok
(
DepNode
::
new_no_params
(
tcx
,
kind
)),
FingerprintStyle
::
DefPathHash
=>
{
Ok
(
DepNode
::
from_def_path_hash
(
tcx
,
def_path_hash
,
kind
))
}
}
}
...
...
compiler/rustc_middle/src/dep_graph/mod.rs
浏览文件 @
b09de95f
...
...
@@ -12,7 +12,7 @@
SerializedDepNodeIndex
,
WorkProduct
,
WorkProductId
,
};
pub
use
dep_node
::{
label_strs
,
DepKind
,
DepNode
,
DepNodeExt
};
pub
use
dep_node
::{
label_strs
,
DepKind
,
Dep
KindStruct
,
Dep
Node
,
DepNodeExt
};
crate
use
dep_node
::{
make_compile_codegen_unit
,
make_compile_mono_item
};
pub
type
DepGraph
=
rustc_query_system
::
dep_graph
::
DepGraph
<
DepKind
>
;
...
...
@@ -24,16 +24,6 @@
impl
rustc_query_system
::
dep_graph
::
DepKind
for
DepKind
{
const
NULL
:
Self
=
DepKind
::
Null
;
#[inline(always)]
fn
fingerprint_style
(
&
self
)
->
rustc_query_system
::
dep_graph
::
FingerprintStyle
{
DepKind
::
fingerprint_style
(
self
)
}
#[inline(always)]
fn
is_eval_always
(
&
self
)
->
bool
{
self
.is_eval_always
}
fn
debug_node
(
node
:
&
DepNode
,
f
:
&
mut
std
::
fmt
::
Formatter
<
'_
>
)
->
std
::
fmt
::
Result
{
write!
(
f
,
"{:?}("
,
node
.kind
)
?
;
...
...
@@ -99,4 +89,14 @@ fn profiler(&self) -> &SelfProfilerRef {
fn
sess
(
&
self
)
->
&
Session
{
self
.sess
}
#[inline(always)]
fn
fingerprint_style
(
&
self
,
kind
:
DepKind
)
->
rustc_query_system
::
dep_graph
::
FingerprintStyle
{
kind
.fingerprint_style
(
*
self
)
}
#[inline(always)]
fn
is_eval_always
(
&
self
,
kind
:
DepKind
)
->
bool
{
self
.query_kind
(
kind
)
.is_eval_always
}
}
compiler/rustc_middle/src/ty/context.rs
浏览文件 @
b09de95f
//! Type context book-keeping.
use
crate
::
arena
::
Arena
;
use
crate
::
dep_graph
::
DepGraph
;
use
crate
::
dep_graph
::
{
DepGraph
,
DepKind
,
DepKindStruct
}
;
use
crate
::
hir
::
place
::
Place
as
HirPlace
;
use
crate
::
infer
::
canonical
::{
Canonical
,
CanonicalVarInfo
,
CanonicalVarInfos
};
use
crate
::
lint
::{
struct_lint_level
,
LintDiagnosticBuilder
,
LintLevelSource
};
...
...
@@ -1011,6 +1011,7 @@ pub struct GlobalCtxt<'tcx> {
pub
queries
:
&
'tcx
dyn
query
::
QueryEngine
<
'tcx
>
,
pub
query_caches
:
query
::
QueryCaches
<
'tcx
>
,
query_kinds
:
&
'tcx
[
DepKindStruct
],
// Internal caches for metadata decoding. No need to track deps on this.
pub
ty_rcache
:
Lock
<
FxHashMap
<
ty
::
CReaderCacheKey
,
Ty
<
'tcx
>>>
,
...
...
@@ -1144,6 +1145,7 @@ pub fn create_global_ctxt(
dep_graph
:
DepGraph
,
on_disk_cache
:
Option
<&
'tcx
dyn
OnDiskCache
<
'tcx
>>
,
queries
:
&
'tcx
dyn
query
::
QueryEngine
<
'tcx
>
,
query_kinds
:
&
'tcx
[
DepKindStruct
],
crate_name
:
&
str
,
output_filenames
:
OutputFilenames
,
)
->
GlobalCtxt
<
'tcx
>
{
...
...
@@ -1170,6 +1172,7 @@ pub fn create_global_ctxt(
on_disk_cache
,
queries
,
query_caches
:
query
::
QueryCaches
::
default
(),
query_kinds
,
ty_rcache
:
Default
::
default
(),
pred_rcache
:
Default
::
default
(),
selection_cache
:
Default
::
default
(),
...
...
@@ -1183,6 +1186,10 @@ pub fn create_global_ctxt(
}
}
pub
fn
query_kind
(
self
,
k
:
DepKind
)
->
&
'tcx
DepKindStruct
{
&
self
.query_kinds
[
k
as
usize
]
}
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
pub
fn
ty_error
(
self
)
->
Ty
<
'tcx
>
{
...
...
compiler/rustc_query_impl/src/lib.rs
浏览文件 @
b09de95f
...
...
@@ -19,7 +19,7 @@
use
rustc_data_structures
::
fingerprint
::
Fingerprint
;
use
rustc_data_structures
::
stable_hasher
::{
HashStable
,
StableHasher
};
use
rustc_errors
::
DiagnosticBuilder
;
use
rustc_middle
::
dep_graph
;
use
rustc_middle
::
dep_graph
::{
self
,
DepKindStruct
}
;
use
rustc_middle
::
ty
::
query
::{
query_keys
,
query_storage
,
query_stored
,
query_values
};
use
rustc_middle
::
ty
::
query
::{
Providers
,
QueryEngine
};
use
rustc_middle
::
ty
::{
self
,
TyCtxt
};
...
...
@@ -29,7 +29,6 @@
#[macro_use]
mod
plumbing
;
pub
use
plumbing
::
QueryCtxt
;
use
plumbing
::
QueryStruct
;
use
rustc_query_system
::
query
::
*
;
mod
stats
;
...
...
compiler/rustc_query_impl/src/plumbing.rs
浏览文件 @
b09de95f
...
...
@@ -55,7 +55,7 @@ fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>> {
fn
try_load_from_on_disk_cache
(
&
self
,
dep_node
:
&
DepNode
)
{
let
cb
=
&
super
::
QUERY_CALLBACKS
[
dep_node
.kind
as
usize
];
(
cb
.try_load_from_on_disk_cache
)(
*
self
,
dep_node
)
(
cb
.try_load_from_on_disk_cache
)(
*
*
self
,
dep_node
)
}
fn
try_force_from_dep_node
(
&
self
,
dep_node
:
&
DepNode
)
->
bool
{
...
...
@@ -80,7 +80,7 @@ fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool {
);
let
cb
=
&
super
::
QUERY_CALLBACKS
[
dep_node
.kind
as
usize
];
(
cb
.force_from_dep_node
)(
*
self
,
dep_node
)
(
cb
.force_from_dep_node
)(
*
*
self
,
dep_node
)
}
// Interactions with on_disk_cache
...
...
@@ -193,60 +193,6 @@ pub fn try_print_query_stack(
}
}
/// This struct stores metadata about each Query.
///
/// Information is retrieved by indexing the `QUERIES` array using the integer value
/// of the `DepKind`. Overall, this allows to implement `QueryContext` using this manual
/// jump table instead of large matches.
pub
struct
QueryStruct
{
/// The red/green evaluation system will try to mark a specific DepNode in the
/// dependency graph as green by recursively trying to mark the dependencies of
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
/// where we don't know if it is red or green and we therefore actually have
/// to recompute its value in order to find out. Since the only piece of
/// information that we have at that point is the `DepNode` we are trying to
/// re-evaluate, we need some way to re-run a query from just that. This is what
/// `force_from_dep_node()` implements.
///
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
/// is usually constructed by computing a stable hash of the query-key that the
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
/// back from hash to query-key (since hash functions are not reversible). For
/// this reason `force_from_dep_node()` is expected to fail from time to time
/// because we just cannot find out, from the `DepNode` alone, what the
/// corresponding query-key is and therefore cannot re-run the query.
///
/// The system deals with this case letting `try_mark_green` fail which forces
/// the root query to be re-evaluated.
///
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
/// Fortunately, we can use some contextual information that will allow us to
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
/// valid `DefPathHash`. Since we also always build a huge table that maps every
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
/// everything we need to re-run the query.
///
/// Take the `mir_promoted` query as an example. Like many other queries, it
/// just has a single parameter: the `DefId` of the item it will compute the
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
/// `DefId` in `tcx.def_path_hash_to_def_id`.
///
/// When you implement a new query, it will likely have a corresponding new
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
/// add it to the "We don't have enough information to reconstruct..." group in
/// the match below.
pub
(
crate
)
force_from_dep_node
:
fn
(
tcx
:
QueryCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
->
bool
,
/// Invoke a query to put the on-disk cached value in memory.
pub
(
crate
)
try_load_from_on_disk_cache
:
fn
(
QueryCtxt
<
'_
>
,
&
DepNode
),
}
macro_rules!
handle_cycle_error
{
([][
$tcx
:
expr
,
$error:expr
])
=>
{{
$error
.emit
();
...
...
@@ -425,28 +371,45 @@ pub mod query_callbacks {
use
rustc_query_system
::
dep_graph
::
FingerprintStyle
;
// We use this for most things when incr. comp. is turned off.
pub
const
Null
:
QueryStruct
=
QueryStruct
{
pub
const
Null
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Unit
,
force_from_dep_node
:
|
_
,
dep_node
|
bug!
(
"force_from_dep_node: encountered {:?}"
,
dep_node
),
try_load_from_on_disk_cache
:
|
_
,
_
|
{},
};
pub
const
TraitSelect
:
QueryStruct
=
QueryStruct
{
pub
const
TraitSelect
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
true
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Unit
,
force_from_dep_node
:
|
_
,
_
|
false
,
try_load_from_on_disk_cache
:
|
_
,
_
|
{},
};
pub
const
CompileCodegenUnit
:
QueryStruct
=
QueryStruct
{
pub
const
CompileCodegenUnit
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Opaque
,
force_from_dep_node
:
|
_
,
_
|
false
,
try_load_from_on_disk_cache
:
|
_
,
_
|
{},
};
pub
const
CompileMonoItem
:
QueryStruct
=
QueryStruct
{
pub
const
CompileMonoItem
:
DepKindStruct
=
DepKindStruct
{
is_anon
:
false
,
is_eval_always
:
false
,
fingerprint_style
:
||
FingerprintStyle
::
Opaque
,
force_from_dep_node
:
|
_
,
_
|
false
,
try_load_from_on_disk_cache
:
|
_
,
_
|
{},
};
$
(
pub
const
$name
:
Query
Struct
=
{
$
(
pub
const
$name
:
DepKind
Struct
=
{
const
is_anon
:
bool
=
is_anon!
([
$
(
$modifiers
)
*
]);
const
is_eval_always
:
bool
=
is_eval_always!
([
$
(
$modifiers
)
*
]);
#[inline(always)]
fn
fingerprint_style
()
->
FingerprintStyle
{
...
...
@@ -458,11 +421,13 @@ fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<query_keys::$n
<
query_keys
::
$name
<
'_
>
as
DepNodeParams
<
TyCtxt
<
'_
>>>
::
recover
(
tcx
,
dep_node
)
}
fn
force_from_dep_node
(
tcx
:
QueryCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
->
bool
{
fn
force_from_dep_node
(
tcx
:
TyCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
->
bool
{
let
tcx
=
QueryCtxt
::
from_tcx
(
tcx
);
force_query
::
<
queries
::
$name
<
'_
>
,
_
>
(
tcx
,
dep_node
)
}
fn
try_load_from_on_disk_cache
(
tcx
:
QueryCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
{
fn
try_load_from_on_disk_cache
(
tcx
:
TyCtxt
<
'_
>
,
dep_node
:
&
DepNode
)
{
let
tcx
=
QueryCtxt
::
from_tcx
(
tcx
);
if
is_anon
{
return
}
...
...
@@ -479,14 +444,17 @@ fn try_load_from_on_disk_cache(tcx: QueryCtxt<'_>, dep_node: &DepNode) {
}
}
QueryStruct
{
DepKindStruct
{
is_anon
,
is_eval_always
,
fingerprint_style
,
force_from_dep_node
,
try_load_from_on_disk_cache
,
}
};)
*
}
static
QUERY_CALLBACKS
:
&
[
Query
Struct
]
=
&
make_dep_kind_array!
(
query_callbacks
);
pub
static
QUERY_CALLBACKS
:
&
[
DepKind
Struct
]
=
&
make_dep_kind_array!
(
query_callbacks
);
}
}
...
...
compiler/rustc_query_system/src/dep_graph/dep_node.rs
浏览文件 @
b09de95f
...
...
@@ -60,8 +60,11 @@ impl<K: DepKind> DepNode<K> {
/// Creates a new, parameterless DepNode. This method will assert
/// that the DepNode corresponding to the given DepKind actually
/// does not require any parameters.
pub
fn
new_no_params
(
kind
:
K
)
->
DepNode
<
K
>
{
debug_assert_eq!
(
kind
.fingerprint_style
(),
FingerprintStyle
::
Unit
);
pub
fn
new_no_params
<
Ctxt
>
(
tcx
:
Ctxt
,
kind
:
K
)
->
DepNode
<
K
>
where
Ctxt
:
super
::
DepContext
<
DepKind
=
K
>
,
{
debug_assert_eq!
(
tcx
.fingerprint_style
(
kind
),
FingerprintStyle
::
Unit
);
DepNode
{
kind
,
hash
:
Fingerprint
::
ZERO
.into
()
}
}
...
...
@@ -75,7 +78,7 @@ pub fn construct<Ctxt, Key>(tcx: Ctxt, kind: K, arg: &Key) -> DepNode<K>
#[cfg(debug_assertions)]
{
if
!
kind
.fingerprint_style
(
)
.reconstructible
()
if
!
tcx
.fingerprint_style
(
kind
)
.reconstructible
()
&&
(
tcx
.sess
()
.opts.debugging_opts.incremental_info
||
tcx
.sess
()
.opts.debugging_opts.query_dep_graph
)
{
...
...
compiler/rustc_query_system/src/dep_graph/graph.rs
浏览文件 @
b09de95f
...
...
@@ -252,7 +252,7 @@ fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
key
);
let
task_deps
=
if
key
.kind
.is_eval_always
(
)
{
let
task_deps
=
if
cx
.dep_context
()
.is_eval_always
(
key
.kind
)
{
None
}
else
{
Some
(
Lock
::
new
(
TaskDeps
{
...
...
@@ -316,7 +316,7 @@ pub fn with_anon_task<Ctxt: DepContext<DepKind = K>, OP, R>(
where
OP
:
FnOnce
()
->
R
,
{
debug_assert!
(
!
dep_kind
.is_eval_always
(
));
debug_assert!
(
!
cx
.is_eval_always
(
dep_kind
));
if
let
Some
(
ref
data
)
=
self
.data
{
let
task_deps
=
Lock
::
new
(
TaskDeps
::
default
());
...
...
@@ -493,7 +493,7 @@ pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>(
tcx
:
Ctxt
,
dep_node
:
&
DepNode
<
K
>
,
)
->
Option
<
(
SerializedDepNodeIndex
,
DepNodeIndex
)
>
{
debug_assert!
(
!
dep_node
.kind
.is_eval_always
(
));
debug_assert!
(
!
tcx
.dep_context
()
.is_eval_always
(
dep_node
.kind
));
// Return None if the dep graph is disabled
let
data
=
self
.data
.as_ref
()
?
;
...
...
@@ -553,7 +553,7 @@ fn try_mark_parent_green<Ctxt: QueryContext<DepKind = K>>(
// We don't know the state of this dependency. If it isn't
// an eval_always node, let's try to mark it green recursively.
if
!
dep_dep_node
.kind
.is_eval_always
(
)
{
if
!
tcx
.dep_context
()
.is_eval_always
(
dep_dep_node
.kind
)
{
debug!
(
"try_mark_previous_green({:?}) --- state of dependency {:?} ({})
\
is unknown, trying to mark it green"
,
...
...
@@ -643,7 +643,7 @@ fn try_mark_previous_green<Ctxt: QueryContext<DepKind = K>>(
}
// We never try to mark eval_always nodes as green
debug_assert!
(
!
dep_node
.kind
.is_eval_always
(
));
debug_assert!
(
!
tcx
.dep_context
()
.is_eval_always
(
dep_node
.kind
));
debug_assert_eq!
(
data
.previous
.index_to_node
(
prev_dep_node_index
),
*
dep_node
);
...
...
compiler/rustc_query_system/src/dep_graph/mod.rs
浏览文件 @
b09de95f
...
...
@@ -32,6 +32,11 @@ pub trait DepContext: Copy {
/// Access the compiler session.
fn
sess
(
&
self
)
->
&
Session
;
/// Return whether this kind always require evaluation.
fn
is_eval_always
(
&
self
,
kind
:
Self
::
DepKind
)
->
bool
;
fn
fingerprint_style
(
&
self
,
kind
:
Self
::
DepKind
)
->
FingerprintStyle
;
}
pub
trait
HasDepContext
:
Copy
{
...
...
@@ -75,9 +80,6 @@ pub fn reconstructible(self) -> bool {
pub
trait
DepKind
:
Copy
+
fmt
::
Debug
+
Eq
+
Hash
+
Send
+
Encodable
<
FileEncoder
>
+
'static
{
const
NULL
:
Self
;
/// Return whether this kind always require evaluation.
fn
is_eval_always
(
&
self
)
->
bool
;
/// Implementation of `std::fmt::Debug` for `DepNode`.
fn
debug_node
(
node
:
&
DepNode
<
Self
>
,
f
:
&
mut
fmt
::
Formatter
<
'_
>
)
->
fmt
::
Result
;
...
...
@@ -90,6 +92,4 @@ fn with_deps<OP, R>(deps: Option<&Lock<TaskDeps<Self>>>, op: OP) -> R
fn
read_deps
<
OP
>
(
op
:
OP
)
where
OP
:
for
<
'a
>
FnOnce
(
Option
<&
'a
Lock
<
TaskDeps
<
Self
>>>
);
fn
fingerprint_style
(
&
self
)
->
FingerprintStyle
;
}
compiler/rustc_query_system/src/query/plumbing.rs
浏览文件 @
b09de95f
...
...
@@ -2,7 +2,7 @@
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
use
crate
::
dep_graph
::{
DepContext
,
Dep
Kind
,
Dep
Node
,
DepNodeIndex
,
DepNodeParams
};
use
crate
::
dep_graph
::{
DepContext
,
DepNode
,
DepNodeIndex
,
DepNodeParams
};
use
crate
::
query
::
caches
::
QueryCache
;
use
crate
::
query
::
config
::{
QueryDescription
,
QueryVtable
,
QueryVtableExt
};
use
crate
::
query
::
job
::{
...
...
@@ -520,14 +520,6 @@ fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
let
result
=
query
.try_load_from_disk
(
tcx
,
prev_dep_node_index
);
prof_timer
.finish_with_query_invocation_id
(
dep_node_index
.into
());
// We always expect to find a cached result for things that
// can be forced from `DepNode`.
debug_assert!
(
!
dep_node
.kind
.fingerprint_style
()
.reconstructible
()
||
result
.is_some
(),
"missing on-disk cache entry for {:?}"
,
dep_node
);
if
let
Some
(
result
)
=
result
{
// If `-Zincremental-verify-ich` is specified, re-hash results from
// the cache and make sure that they have the expected fingerprint.
...
...
@@ -537,6 +529,14 @@ fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
return
Some
((
result
,
dep_node_index
));
}
// We always expect to find a cached result for things that
// can be forced from `DepNode`.
debug_assert!
(
!
tcx
.dep_context
()
.fingerprint_style
(
dep_node
.kind
)
.reconstructible
(),
"missing on-disk cache entry for {:?}"
,
dep_node
);
}
// We could not load a result from the on-disk cache, so
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录