Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8b22ed86
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
8b22ed86
编写于
12月 22, 2015
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add assert-dep-graph testing mechanism and tests
上级
d48f48f6
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
782 addition
and
0 deletion
+782
-0
src/librustc_trans/lib.rs
src/librustc_trans/lib.rs
+1
-0
src/librustc_trans/trans/assert_dep_graph.rs
src/librustc_trans/trans/assert_dep_graph.rs
+430
-0
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/base.rs
+3
-0
src/librustc_trans/trans/mod.rs
src/librustc_trans/trans/mod.rs
+1
-0
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+8
-0
src/test/compile-fail/dep-graph-caller-callee.rs
src/test/compile-fail/dep-graph-caller-callee.rs
+44
-0
src/test/compile-fail/dep-graph-struct-signature.rs
src/test/compile-fail/dep-graph-struct-signature.rs
+97
-0
src/test/compile-fail/dep-graph-trait-impl-two-traits-same-method.rs
...mpile-fail/dep-graph-trait-impl-two-traits-same-method.rs
+51
-0
src/test/compile-fail/dep-graph-trait-impl-two-traits.rs
src/test/compile-fail/dep-graph-trait-impl-two-traits.rs
+52
-0
src/test/compile-fail/dep-graph-trait-impl.rs
src/test/compile-fail/dep-graph-trait-impl.rs
+75
-0
src/test/compile-fail/dep-graph-unrelated.rs
src/test/compile-fail/dep-graph-unrelated.rs
+20
-0
未找到文件。
src/librustc_trans/lib.rs
浏览文件 @
8b22ed86
...
...
@@ -27,6 +27,7 @@
#![feature(const_fn)]
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#![feature(into_cow)]
#![feature(iter_arith)]
#![feature(libc)]
#![feature(path_relative_from)]
...
...
src/librustc_trans/trans/assert_dep_graph.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-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.
//! This pass is only used for the UNIT TESTS and DEBUGGING NEEDS
//! around dependency graph construction. It serves two purposes; it
//! will dump graphs in graphviz form to disk, and it searches for
//! `#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]`
//! annotations. These annotations can be used to test whether paths
//! exist in the graph. We report errors on each
//! `rustc_if_this_changed` annotation. If a path exists in all
//! cases, then we would report "all path(s) exist". Otherwise, we
//! report: "no path to `foo`" for each case where no path exists.
//! `compile-fail` tests can then be used to check when paths exist or
//! do not.
//!
//! The full form of the `rustc_if_this_changed` annotation is
//! `#[rustc_if_this_changed(id)]`. The `"id"` is optional and
//! defaults to `"id"` if omitted.
//!
//! Example:
//!
//! ```
//! #[rustc_if_this_changed]
//! fn foo() { }
//!
//! #[rustc_then_this_would_need("trans")] //~ ERROR no path from `foo`
//! fn bar() { }
//!
//! #[rustc_then_this_would_need("trans")] //~ ERROR OK
//! fn baz() { foo(); }
//! ```
use
graphviz
as
dot
;
use
rustc
::
dep_graph
::{
DepGraphQuery
,
DepNode
};
use
rustc
::
middle
::
def_id
::
DefId
;
use
rustc
::
middle
::
ty
;
use
rustc_data_structures
::
fnv
::{
FnvHashMap
,
FnvHashSet
};
use
rustc_data_structures
::
graph
::{
Direction
,
INCOMING
,
OUTGOING
,
NodeIndex
};
use
rustc_front
::
hir
;
use
rustc_front
::
intravisit
::
Visitor
;
use
std
::
borrow
::
IntoCow
;
use
std
::
env
;
use
std
::
fs
::
File
;
use
std
::
io
::
Write
;
use
syntax
::
ast
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
parse
::
token
::
InternedString
;
const
IF_THIS_CHANGED
:
&
'static
str
=
"rustc_if_this_changed"
;
const
THEN_THIS_WOULD_NEED
:
&
'static
str
=
"rustc_then_this_would_need"
;
const
ID
:
&
'static
str
=
"id"
;
pub
fn
assert_dep_graph
(
tcx
:
&
ty
::
ctxt
)
{
let
_
ignore
=
tcx
.dep_graph
.in_ignore
();
if
tcx
.sess.opts.dump_dep_graph
{
dump_graph
(
tcx
);
}
// Find annotations supplied by user (if any).
let
(
if_this_changed
,
then_this_would_need
)
=
{
let
mut
visitor
=
IfThisChanged
{
tcx
:
tcx
,
if_this_changed
:
FnvHashMap
(),
then_this_would_need
:
FnvHashMap
()
};
tcx
.map
.krate
()
.visit_all_items
(
&
mut
visitor
);
(
visitor
.if_this_changed
,
visitor
.then_this_would_need
)
};
// Check paths.
check_paths
(
tcx
,
&
if_this_changed
,
&
then_this_would_need
);
}
type
SourceHashMap
=
FnvHashMap
<
InternedString
,
FnvHashSet
<
(
Span
,
DefId
,
DepNode
)
>>
;
type
TargetHashMap
=
FnvHashMap
<
InternedString
,
FnvHashSet
<
(
Span
,
InternedString
,
ast
::
NodeId
,
DepNode
)
>>
;
struct
IfThisChanged
<
'a
,
'tcx
:
'a
>
{
tcx
:
&
'a
ty
::
ctxt
<
'tcx
>
,
if_this_changed
:
SourceHashMap
,
then_this_would_need
:
TargetHashMap
,
}
impl
<
'a
,
'tcx
>
IfThisChanged
<
'a
,
'tcx
>
{
fn
process_attrs
(
&
mut
self
,
node_id
:
ast
::
NodeId
,
def_id
:
DefId
)
{
for
attr
in
self
.tcx
.get_attrs
(
def_id
)
.iter
()
{
if
attr
.check_name
(
IF_THIS_CHANGED
)
{
let
mut
id
=
None
;
for
meta_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
match
meta_item
.node
{
ast
::
MetaWord
(
ref
s
)
if
id
.is_none
()
=>
id
=
Some
(
s
.clone
()),
_
=>
{
self
.tcx.sess
.span_err
(
meta_item
.span
,
&
format!
(
"unexpected meta-item {:?}"
,
meta_item
.node
));
}
}
}
let
id
=
id
.unwrap_or
(
InternedString
::
new
(
ID
));
self
.if_this_changed
.entry
(
id
)
.or_insert
(
FnvHashSet
())
.insert
((
attr
.span
,
def_id
,
DepNode
::
Hir
(
def_id
)));
}
else
if
attr
.check_name
(
THEN_THIS_WOULD_NEED
)
{
let
mut
dep_node_interned
=
None
;
let
mut
id
=
None
;
for
meta_item
in
attr
.meta_item_list
()
.unwrap_or_default
()
{
match
meta_item
.node
{
ast
::
MetaWord
(
ref
s
)
if
dep_node_interned
.is_none
()
=>
dep_node_interned
=
Some
(
s
.clone
()),
ast
::
MetaWord
(
ref
s
)
if
id
.is_none
()
=>
id
=
Some
(
s
.clone
()),
_
=>
{
self
.tcx.sess
.span_err
(
meta_item
.span
,
&
format!
(
"unexpected meta-item {:?}"
,
meta_item
.node
));
}
}
}
let
dep_node_str
=
dep_node_interned
.as_ref
()
.map
(|
s
|
&**
s
);
macro_rules!
match_depnode_name
{
(
$input:expr
,
$def_id:expr
,
match
{
$
(
$variant:ident
,)
*
}
else
$y:expr
)
=>
{
match
$input
{
$
(
Some
(
stringify!
(
$variant
))
=>
DepNode
::
$variant
(
$def_id
),)
*
_
=>
$y
}
}
}
let
dep_node
=
match_depnode_name!
{
dep_node_str
,
def_id
,
match
{
CollectItem
,
BorrowCheck
,
TransCrateItem
,
TypeckItemType
,
TypeckItemBody
,
ImplOrTraitItems
,
ItemSignature
,
FieldTy
,
TraitItemDefIds
,
InherentImpls
,
ImplItems
,
TraitImpls
,
ReprHints
,
}
else
{
self
.tcx.sess
.span_fatal
(
attr
.span
,
&
format!
(
"unrecognized DepNode variant {:?}"
,
dep_node_str
));
}
};
let
id
=
id
.unwrap_or
(
InternedString
::
new
(
ID
));
self
.then_this_would_need
.entry
(
id
)
.or_insert
(
FnvHashSet
())
.insert
((
attr
.span
,
dep_node_interned
.clone
()
.unwrap
(),
node_id
,
dep_node
));
}
}
}
}
impl
<
'a
,
'tcx
>
Visitor
<
'tcx
>
for
IfThisChanged
<
'a
,
'tcx
>
{
fn
visit_item
(
&
mut
self
,
item
:
&
'tcx
hir
::
Item
)
{
let
def_id
=
self
.tcx.map
.local_def_id
(
item
.id
);
self
.process_attrs
(
item
.id
,
def_id
);
}
}
fn
check_paths
(
tcx
:
&
ty
::
ctxt
,
if_this_changed
:
&
SourceHashMap
,
then_this_would_need
:
&
TargetHashMap
)
{
// Return early here so as not to construct the query, which is not cheap.
if
if_this_changed
.is_empty
()
{
return
;
}
let
query
=
tcx
.dep_graph
.query
();
for
(
id
,
sources
)
in
if_this_changed
{
let
targets
=
match
then_this_would_need
.get
(
id
)
{
Some
(
targets
)
=>
targets
,
None
=>
{
for
&
(
source_span
,
_
,
_
)
in
sources
.iter
()
.take
(
1
)
{
tcx
.sess
.span_err
(
source_span
,
&
format!
(
"no targets for id `{}`"
,
id
));
}
continue
;
}
};
for
&
(
_
,
source_def_id
,
source_dep_node
)
in
sources
{
let
dependents
=
query
.dependents
(
source_dep_node
);
for
&
(
target_span
,
ref
target_pass
,
_
,
ref
target_dep_node
)
in
targets
{
if
!
dependents
.contains
(
&
target_dep_node
)
{
tcx
.sess
.span_err
(
target_span
,
&
format!
(
"no path from `{}` to `{}`"
,
tcx
.item_path_str
(
source_def_id
),
target_pass
));
}
else
{
tcx
.sess
.span_err
(
target_span
,
&
format!
(
"OK"
));
}
}
}
}
}
fn
dump_graph
(
tcx
:
&
ty
::
ctxt
)
{
let
path
:
String
=
env
::
var
(
"RUST_DEP_GRAPH"
)
.unwrap_or_else
(|
_
|
format!
(
"dep_graph"
));
let
query
=
tcx
.dep_graph
.query
();
let
nodes
=
match
env
::
var
(
"RUST_DEP_GRAPH_FILTER"
)
{
Ok
(
string
)
=>
{
// Expect one of: "-> target", "source -> target", or "source ->".
let
parts
:
Vec
<
_
>
=
string
.split
(
"->"
)
.collect
();
if
parts
.len
()
>
2
{
panic!
(
"Invalid RUST_DEP_GRAPH_FILTER: expected '[source] -> [target]'"
);
}
let
sources
=
node_set
(
&
query
,
&
parts
[
0
]);
let
targets
=
node_set
(
&
query
,
&
parts
[
1
]);
filter_nodes
(
&
query
,
&
sources
,
&
targets
)
}
Err
(
_
)
=>
{
query
.nodes
()
.into_iter
()
.collect
()
}
};
let
edges
=
filter_edges
(
&
query
,
&
nodes
);
{
// dump a .txt file with just the edges:
let
txt_path
=
format!
(
"{}.txt"
,
path
);
let
mut
file
=
File
::
create
(
&
txt_path
)
.unwrap
();
for
&
(
source
,
target
)
in
&
edges
{
write!
(
file
,
"{:?} -> {:?}
\n
"
,
source
,
target
)
.unwrap
();
}
}
{
// dump a .dot file in graphviz format:
let
dot_path
=
format!
(
"{}.dot"
,
path
);
let
mut
v
=
Vec
::
new
();
dot
::
render
(
&
GraphvizDepGraph
(
nodes
,
edges
),
&
mut
v
)
.unwrap
();
File
::
create
(
&
dot_path
)
.and_then
(|
mut
f
|
f
.write_all
(
&
v
))
.unwrap
();
}
}
pub
struct
GraphvizDepGraph
(
FnvHashSet
<
DepNode
>
,
Vec
<
(
DepNode
,
DepNode
)
>
);
impl
<
'a
,
'tcx
>
dot
::
GraphWalk
<
'a
,
DepNode
,
(
DepNode
,
DepNode
)
>
for
GraphvizDepGraph
{
fn
nodes
(
&
self
)
->
dot
::
Nodes
<
DepNode
>
{
let
nodes
:
Vec
<
_
>
=
self
.0
.iter
()
.cloned
()
.collect
();
nodes
.into_cow
()
}
fn
edges
(
&
self
)
->
dot
::
Edges
<
(
DepNode
,
DepNode
)
>
{
self
.1
[
..
]
.into_cow
()
}
fn
source
(
&
self
,
edge
:
&
(
DepNode
,
DepNode
))
->
DepNode
{
edge
.0
}
fn
target
(
&
self
,
edge
:
&
(
DepNode
,
DepNode
))
->
DepNode
{
edge
.1
}
}
impl
<
'a
,
'tcx
>
dot
::
Labeller
<
'a
,
DepNode
,
(
DepNode
,
DepNode
)
>
for
GraphvizDepGraph
{
fn
graph_id
(
&
self
)
->
dot
::
Id
{
dot
::
Id
::
new
(
"DependencyGraph"
)
.unwrap
()
}
fn
node_id
(
&
self
,
n
:
&
DepNode
)
->
dot
::
Id
{
let
s
:
String
=
format!
(
"{:?}"
,
n
)
.chars
()
.map
(|
c
|
if
c
==
'_'
||
c
.is_alphanumeric
()
{
c
}
else
{
'_'
})
.collect
();
debug!
(
"n={:?} s={:?}"
,
n
,
s
);
dot
::
Id
::
new
(
s
)
.unwrap
()
}
fn
node_label
(
&
self
,
n
:
&
DepNode
)
->
dot
::
LabelText
{
dot
::
LabelText
::
label
(
format!
(
"{:?}"
,
n
))
}
}
// Given an optional filter like `"x,y,z"`, returns either `None` (no
// filter) or the set of nodes whose labels contain all of those
// substrings.
fn
node_set
(
query
:
&
DepGraphQuery
,
filter
:
&
str
)
->
Option
<
FnvHashSet
<
DepNode
>>
{
debug!
(
"node_set(filter={:?})"
,
filter
);
if
filter
.trim
()
.is_empty
()
{
return
None
;
}
let
filters
:
Vec
<&
str
>
=
filter
.split
(
"&"
)
.map
(|
s
|
s
.trim
())
.collect
();
debug!
(
"node_set: filters={:?}"
,
filters
);
Some
(
query
.nodes
()
.into_iter
()
.filter
(|
n
|
{
let
s
=
format!
(
"{:?}"
,
n
);
filters
.iter
()
.all
(|
f
|
s
.contains
(
f
))
})
.collect
())
}
fn
filter_nodes
(
query
:
&
DepGraphQuery
,
sources
:
&
Option
<
FnvHashSet
<
DepNode
>>
,
targets
:
&
Option
<
FnvHashSet
<
DepNode
>>
)
->
FnvHashSet
<
DepNode
>
{
if
let
&
Some
(
ref
sources
)
=
sources
{
if
let
&
Some
(
ref
targets
)
=
targets
{
walk_between
(
query
,
sources
,
targets
)
}
else
{
walk_nodes
(
query
,
sources
,
OUTGOING
)
}
}
else
if
let
&
Some
(
ref
targets
)
=
targets
{
walk_nodes
(
query
,
targets
,
INCOMING
)
}
else
{
query
.nodes
()
.into_iter
()
.collect
()
}
}
fn
walk_nodes
(
query
:
&
DepGraphQuery
,
starts
:
&
FnvHashSet
<
DepNode
>
,
direction
:
Direction
)
->
FnvHashSet
<
DepNode
>
{
let
mut
set
=
FnvHashSet
();
for
start
in
starts
{
debug!
(
"walk_nodes: start={:?} outgoing?={:?}"
,
start
,
direction
==
OUTGOING
);
if
set
.insert
(
*
start
)
{
let
mut
stack
=
vec!
[
query
.indices
[
start
]];
while
let
Some
(
index
)
=
stack
.pop
()
{
for
(
_
,
edge
)
in
query
.graph
.adjacent_edges
(
index
,
direction
)
{
let
neighbor_index
=
edge
.source_or_target
(
direction
);
let
neighbor
=
query
.graph
.node_data
(
neighbor_index
);
if
set
.insert
(
*
neighbor
)
{
stack
.push
(
neighbor_index
);
}
}
}
}
}
set
}
fn
walk_between
(
query
:
&
DepGraphQuery
,
sources
:
&
FnvHashSet
<
DepNode
>
,
targets
:
&
FnvHashSet
<
DepNode
>
)
->
FnvHashSet
<
DepNode
>
{
// This is a bit tricky. We want to include a node only if it is:
// (a) reachable from a source and (b) will reach a target. And we
// have to be careful about cycles etc. Luckily efficiency is not
// a big concern!
#[derive(Copy,
Clone,
PartialEq)]
enum
State
{
Undecided
,
Deciding
,
Included
,
Excluded
}
let
mut
node_states
=
vec!
[
State
::
Undecided
;
query
.graph
.len_nodes
()];
for
&
target
in
targets
{
node_states
[
query
.indices
[
&
target
]
.0
]
=
State
::
Included
;
}
for
source
in
sources
.iter
()
.map
(|
n
|
query
.indices
[
n
])
{
recurse
(
query
,
&
mut
node_states
,
source
);
}
return
query
.nodes
()
.into_iter
()
.filter
(|
n
|
{
let
index
=
query
.indices
[
n
];
node_states
[
index
.0
]
==
State
::
Included
})
.collect
();
fn
recurse
(
query
:
&
DepGraphQuery
,
node_states
:
&
mut
[
State
],
node
:
NodeIndex
)
->
bool
{
match
node_states
[
node
.0
]
{
// known to reach a target
State
::
Included
=>
return
true
,
// known not to reach a target
State
::
Excluded
=>
return
false
,
// backedge, not yet known, say false
State
::
Deciding
=>
return
false
,
State
::
Undecided
=>
{
}
}
node_states
[
node
.0
]
=
State
::
Deciding
;
for
neighbor_index
in
query
.graph
.successor_nodes
(
node
)
{
if
recurse
(
query
,
node_states
,
neighbor_index
)
{
node_states
[
node
.0
]
=
State
::
Included
;
}
}
// if we didn't find a path to target, then set to excluded
if
node_states
[
node
.0
]
==
State
::
Deciding
{
node_states
[
node
.0
]
=
State
::
Excluded
;
false
}
else
{
assert
!
(
node_states
[
node
.0
]
==
State
::
Included
);
true
}
}
}
fn
filter_edges
(
query
:
&
DepGraphQuery
,
nodes
:
&
FnvHashSet
<
DepNode
>
)
->
Vec
<
(
DepNode
,
DepNode
)
>
{
query
.edges
()
.into_iter
()
.filter
(|
&
(
source
,
target
)|
nodes
.contains
(
&
source
)
&&
nodes
.contains
(
&
target
))
.collect
()
}
src/librustc_trans/trans/base.rs
浏览文件 @
8b22ed86
...
...
@@ -51,6 +51,7 @@
use
session
::
Session
;
use
trans
::
_
match
;
use
trans
::
adt
;
use
trans
::
assert_dep_graph
;
use
trans
::
attributes
;
use
trans
::
build
::
*
;
use
trans
::
builder
::{
Builder
,
noname
};
...
...
@@ -3142,6 +3143,8 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
};
let
no_builtins
=
attr
::
contains_name
(
&
krate
.attrs
,
"no_builtins"
);
assert_dep_graph
::
assert_dep_graph
(
tcx
);
CrateTranslation
{
modules
:
modules
,
metadata_module
:
metadata_module
,
...
...
src/librustc_trans/trans/mod.rs
浏览文件 @
8b22ed86
...
...
@@ -20,6 +20,7 @@
mod
adt
;
mod
asm
;
mod
assert_dep_graph
;
mod
attributes
;
mod
base
;
mod
basic_block
;
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
8b22ed86
...
...
@@ -326,6 +326,14 @@ enum Status {
"the `#[rustc_error]` attribute
\
is just used for rustc unit tests
\
and will never be stable"
)),
(
"rustc_if_this_changed"
,
Whitelisted
,
Gated
(
"rustc_attrs"
,
"the `#[rustc_if_this_changed]` attribute
\
is just used for rustc unit tests
\
and will never be stable"
)),
(
"rustc_then_this_would_need"
,
Whitelisted
,
Gated
(
"rustc_attrs"
,
"the `#[rustc_if_this_changed]` attribute
\
is just used for rustc unit tests
\
and will never be stable"
)),
(
"rustc_move_fragments"
,
Normal
,
Gated
(
"rustc_attrs"
,
"the `#[rustc_move_fragments]` attribute
\
is just used for rustc unit tests
\
...
...
src/test/compile-fail/dep-graph-caller-callee.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that two unrelated functions have no trans dependency.
#![feature(rustc_attrs)]
#![allow(dead_code)]
fn
main
()
{
}
mod
x
{
#[rustc_if_this_changed]
pub
fn
x
()
{
}
}
mod
y
{
use
x
;
// These dependencies SHOULD exist:
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR OK
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR OK
pub
fn
y
()
{
x
::
x
();
}
}
mod
z
{
use
y
;
// These are expected to yield errors, because changes to `x`
// affect the BODY of `y`, but not its signature.
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR no path
pub
fn
z
()
{
y
::
y
();
}
}
src/test/compile-fail/dep-graph-struct-signature.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that two unrelated functions have no trans dependency.
#![feature(rustc_attrs)]
#![allow(dead_code)]
#![allow(unused_variables)]
fn
main
()
{
}
#[rustc_if_this_changed]
struct
WillChange
{
x
:
u32
,
y
:
u32
}
struct
WontChange
{
x
:
u32
,
y
:
u32
}
// these are valid dependencies
mod
signatures
{
use
WillChange
;
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
trait
Bar
{
fn
do_something
(
x
:
WillChange
);
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
fn
some_fn
(
x
:
WillChange
)
{
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
fn
new_foo
(
x
:
u32
,
y
:
u32
)
->
WillChange
{
WillChange
{
x
:
x
,
y
:
y
}
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
impl
WillChange
{
fn
new
(
x
:
u32
,
y
:
u32
)
->
WillChange
{
loop
{
}
}
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
impl
WillChange
{
fn
method
(
&
self
,
x
:
u32
)
{
}
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
struct
WillChanges
{
x
:
WillChange
,
y
:
WillChange
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
fn
indirect
(
x
:
WillChange
)
{
}
}
// these are invalid dependencies, though sometimes we create edges
// anyway.
mod
invalid_signatures
{
use
WontChange
;
// FIXME due to the variance pass having overly conservative edges,
// we incorrectly think changes are needed here
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
trait
A
{
fn
do_something_else_twice
(
x
:
WontChange
);
}
// FIXME due to the variance pass having overly conservative edges,
// we incorrectly think changes are needed here
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR OK
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR OK
fn
b
(
x
:
WontChange
)
{
}
#[rustc_then_this_would_need(ItemSignature)]
//~ ERROR no path from `WillChange`
#[rustc_then_this_would_need(CollectItem)]
//~ ERROR no path from `WillChange`
fn
c
(
x
:
u32
)
{
}
}
src/test/compile-fail/dep-graph-trait-impl-two-traits-same-method.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that two unrelated functions have no trans dependency.
#![feature(rustc_attrs)]
#![allow(dead_code)]
fn
main
()
{
}
pub
trait
Foo
:
Sized
{
fn
method
(
self
)
{
}
}
pub
trait
Bar
:
Sized
{
fn
method
(
self
)
{
}
}
mod
x
{
use
{
Foo
,
Bar
};
#[rustc_if_this_changed]
impl
Foo
for
u32
{
}
impl
Bar
for
char
{
}
}
mod
y
{
use
{
Foo
,
Bar
};
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR OK
pub
fn
with_char
()
{
char
::
method
(
'a'
);
}
}
mod
z
{
use
y
;
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
pub
fn
z
()
{
y
::
with_char
();
}
}
src/test/compile-fail/dep-graph-trait-impl-two-traits.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that adding an impl to a trait `Foo` does not affect functions
// that only use `Bar`.
#![feature(rustc_attrs)]
#![allow(warnings)]
fn
main
()
{
}
pub
trait
Foo
:
Sized
{
fn
foo
(
self
)
{
}
}
pub
trait
Bar
:
Sized
{
fn
bar
(
self
)
{
}
}
mod
x
{
use
{
Foo
,
Bar
};
#[rustc_if_this_changed]
impl
Foo
for
char
{
}
impl
Bar
for
char
{
}
}
mod
y
{
use
{
Foo
,
Bar
};
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
pub
fn
call_bar
()
{
char
::
bar
(
'a'
);
}
}
mod
z
{
use
y
;
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
pub
fn
z
()
{
y
::
call_bar
();
}
}
src/test/compile-fail/dep-graph-trait-impl.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that two unrelated functions have no trans dependency.
#![feature(rustc_attrs)]
#![allow(warnings)]
fn
main
()
{
}
pub
trait
Foo
:
Sized
{
fn
method
(
self
)
{
}
}
mod
x
{
use
Foo
;
#[rustc_if_this_changed]
impl
Foo
for
char
{
}
impl
Foo
for
u32
{
}
}
mod
y
{
use
Foo
;
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR OK
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR OK
pub
fn
with_char
()
{
char
::
method
(
'a'
);
}
// TODO open an issue on this, problem is that we fail to track
// the tcx fulfillment cache
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR no path
pub
fn
take_foo_with_char
()
{
take_foo
::
<
char
>
(
'a'
);
}
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR OK
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR OK
pub
fn
with_u32
()
{
u32
::
method
(
22
);
}
// TODO same issue as above
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR no path
pub
fn
take_foo_with_u32
()
{
take_foo
::
<
u32
>
(
22
);
}
pub
fn
take_foo
<
T
:
Foo
>
(
t
:
T
)
{
}
}
mod
z
{
use
y
;
// These are expected to yield errors, because changes to `x`
// affect the BODY of `y`, but not its signature.
#[rustc_then_this_would_need(TypeckItemBody)]
//~ ERROR no path
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR no path
pub
fn
z
()
{
y
::
with_char
();
y
::
with_u32
();
}
}
src/test/compile-fail/dep-graph-unrelated.rs
0 → 100644
浏览文件 @
8b22ed86
// Copyright 2012-2014 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.
// Test that two unrelated functions have no trans dependency.
#![feature(rustc_attrs)]
#![allow(dead_code)]
#[rustc_if_this_changed]
fn
main
()
{
}
#[rustc_then_this_would_need(TransCrateItem)]
//~ ERROR no path from `main`
fn
bar
()
{
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录