@@ -18,53 +18,53 @@ use middle::ty;
1818use middle:: infer;
1919use syntax:: ast;
2020use syntax:: codemap:: Span ;
21+ use rustc:: dep_graph:: DepNode ;
2122use rustc_front:: hir;
2223use rustc_front:: intravisit;
23- use util:: nodemap:: DefIdMap ;
24+ use util:: nodemap:: { DefIdMap , DefIdSet } ;
2425
2526pub 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 ( ) } ;
2830
2931 // this secondary walk specifically checks for some other cases,
3032 // 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) ;
3234}
3335
3436struct OverlapChecker < ' cx , ' tcx : ' cx > {
3537 tcx : & ' cx ty:: ctxt < ' tcx > ,
3638
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+
3747 // maps from a trait def-id to an impl id
3848 default_impls : DefIdMap < ast:: NodeId > ,
3949}
4050
4151impl < ' 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 ;
5559 }
56- }
5760
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 ) ;
6364
6465 // We should already know all impls of this trait, so these
6566 // 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 ) ;
6868
6969 // Conflicts can only occur between a blanket impl and another impl,
7070 // or between 2 non-blanket impls of the same kind.
@@ -175,12 +175,20 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
175175impl < ' cx , ' tcx , ' v > intravisit:: Visitor < ' v > for OverlapChecker < ' cx , ' tcx > {
176176 fn visit_item ( & mut self , item : & ' v hir:: Item ) {
177177 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 ( ..) => {
179184 // look for another default impl; note that due to the
180185 // general orphan/coherence rules, it must always be
181186 // in this crate.
182187 let impl_def_id = self . tcx . map . local_def_id ( item. id ) ;
183188 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+
184192 let prev_default_impl = self . default_impls . insert ( trait_ref. def_id , item. id ) ;
185193 match prev_default_impl {
186194 Some ( prev_id) => {
@@ -195,6 +203,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
195203 let impl_def_id = self . tcx . map . local_def_id ( item. id ) ;
196204 let trait_ref = self . tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
197205 let trait_def_id = trait_ref. def_id ;
206+ self . check_for_overlapping_impls_of_trait ( trait_def_id) ;
198207 match trait_ref. self_ty ( ) . sty {
199208 ty:: TyTrait ( ref data) => {
200209 // This is something like impl Trait1 for Trait2. Illegal
0 commit comments