@@ -18,53 +18,53 @@ use middle::ty;
18
18
use middle:: infer;
19
19
use syntax:: ast;
20
20
use syntax:: codemap:: Span ;
21
+ use rustc:: dep_graph:: DepNode ;
21
22
use rustc_front:: hir;
22
23
use rustc_front:: intravisit;
23
- use util:: nodemap:: DefIdMap ;
24
+ use util:: nodemap:: { DefIdMap , DefIdSet } ;
24
25
25
26
pub fn check ( tcx : & ty:: ctxt ) {
26
- let mut overlap = OverlapChecker { tcx : tcx, default_impls : DefIdMap ( ) } ;
27
- overlap. check_for_overlapping_impls ( ) ;
27
+ let mut overlap = OverlapChecker { tcx : tcx,
28
+ traits_checked : DefIdSet ( ) ,
29
+ default_impls : DefIdMap ( ) } ;
28
30
29
31
// this secondary walk specifically checks for some other cases,
30
32
// like defaulted traits, for which additional overlap rules exist
31
- tcx. map . krate ( ) . visit_all_items ( & mut overlap) ;
33
+ tcx. visit_all_items_in_krate ( DepNode :: CoherenceOverlapCheckSpecial , & mut overlap) ;
32
34
}
33
35
34
36
struct OverlapChecker < ' cx , ' tcx : ' cx > {
35
37
tcx : & ' cx ty:: ctxt < ' tcx > ,
36
38
39
+ // The set of traits where we have checked for overlap. This is
40
+ // used to avoid checking the same trait twice.
41
+ //
42
+ // NB. It's ok to skip tracking this set because we fully
43
+ // encapsulate it, and we always create a task
44
+ // (`CoherenceOverlapCheck`) corresponding to each entry.
45
+ traits_checked : DefIdSet ,
46
+
37
47
// maps from a trait def-id to an impl id
38
48
default_impls : DefIdMap < ast:: NodeId > ,
39
49
}
40
50
41
51
impl < ' cx , ' tcx > OverlapChecker < ' cx , ' tcx > {
42
- fn check_for_overlapping_impls ( & self ) {
43
- debug ! ( "check_for_overlapping_impls" ) ;
44
-
45
- // Collect this into a vector to avoid holding the
46
- // refcell-lock during the
47
- // check_for_overlapping_impls_of_trait() check, since that
48
- // check can populate this table further with impls from other
49
- // crates.
50
- let trait_defs: Vec < _ > = self . tcx . trait_defs . borrow ( ) . values ( ) . cloned ( ) . collect ( ) ;
51
-
52
- for trait_def in trait_defs {
53
- self . tcx . populate_implementations_for_trait_if_necessary ( trait_def. trait_ref . def_id ) ;
54
- self . check_for_overlapping_impls_of_trait ( trait_def) ;
52
+ fn check_for_overlapping_impls_of_trait ( & mut self , trait_def_id : DefId ) {
53
+ debug ! ( "check_for_overlapping_impls_of_trait(trait_def_id={:?})" ,
54
+ trait_def_id) ;
55
+
56
+ let _task = self . tcx . dep_graph . in_task ( DepNode :: CoherenceOverlapCheck ( trait_def_id) ) ;
57
+ if !self . traits_checked . insert ( trait_def_id) {
58
+ return ;
55
59
}
56
- }
57
60
58
- fn check_for_overlapping_impls_of_trait ( & self ,
59
- trait_def : & ' tcx ty:: TraitDef < ' tcx > )
60
- {
61
- debug ! ( "check_for_overlapping_impls_of_trait(trait_def={:?})" ,
62
- trait_def) ;
61
+ let trait_def = self . tcx . lookup_trait_def ( trait_def_id) ;
62
+ self . tcx . populate_implementations_for_trait_if_necessary (
63
+ trait_def. trait_ref . def_id ) ;
63
64
64
65
// We should already know all impls of this trait, so these
65
66
// borrows are safe.
66
- let blanket_impls = trait_def. blanket_impls . borrow ( ) ;
67
- let nonblanket_impls = trait_def. nonblanket_impls . borrow ( ) ;
67
+ let ( blanket_impls, nonblanket_impls) = trait_def. borrow_impl_lists ( self . tcx ) ;
68
68
69
69
// Conflicts can only occur between a blanket impl and another impl,
70
70
// or between 2 non-blanket impls of the same kind.
@@ -175,12 +175,20 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
175
175
impl < ' cx , ' tcx , ' v > intravisit:: Visitor < ' v > for OverlapChecker < ' cx , ' tcx > {
176
176
fn visit_item ( & mut self , item : & ' v hir:: Item ) {
177
177
match item. node {
178
- hir:: ItemDefaultImpl ( _, _) => {
178
+ hir:: ItemTrait ( ..) => {
179
+ let trait_def_id = self . tcx . map . local_def_id ( item. id ) ;
180
+ self . check_for_overlapping_impls_of_trait ( trait_def_id) ;
181
+ }
182
+
183
+ hir:: ItemDefaultImpl ( ..) => {
179
184
// look for another default impl; note that due to the
180
185
// general orphan/coherence rules, it must always be
181
186
// in this crate.
182
187
let impl_def_id = self . tcx . map . local_def_id ( item. id ) ;
183
188
let trait_ref = self . tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
189
+
190
+ self . check_for_overlapping_impls_of_trait ( trait_ref. def_id ) ;
191
+
184
192
let prev_default_impl = self . default_impls . insert ( trait_ref. def_id , item. id ) ;
185
193
match prev_default_impl {
186
194
Some ( prev_id) => {
@@ -195,6 +203,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
195
203
let impl_def_id = self . tcx . map . local_def_id ( item. id ) ;
196
204
let trait_ref = self . tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
197
205
let trait_def_id = trait_ref. def_id ;
206
+ self . check_for_overlapping_impls_of_trait ( trait_def_id) ;
198
207
match trait_ref. self_ty ( ) . sty {
199
208
ty:: TyTrait ( ref data) => {
200
209
// This is something like impl Trait1 for Trait2. Illegal
0 commit comments