@@ -18,7 +18,7 @@ use stdx::never;
1818use crate :: {
1919 autoderef:: { self , AutoderefKind } ,
2020 db:: HirDatabase ,
21- from_foreign_def_id,
21+ from_chalk_trait_id , from_foreign_def_id,
2222 infer:: { unify:: InferenceTable , Adjust , Adjustment , AutoBorrow , OverloadedDeref , PointerCast } ,
2323 primitive:: { FloatTy , IntTy , UintTy } ,
2424 static_lifetime, to_chalk_trait_id,
@@ -265,11 +265,12 @@ impl TraitImpls {
265265#[ derive( Debug , Eq , PartialEq ) ]
266266pub struct InherentImpls {
267267 map : FxHashMap < TyFingerprint , Vec < ImplId > > ,
268+ invalid_impls : Vec < ImplId > ,
268269}
269270
270271impl InherentImpls {
271272 pub ( crate ) fn inherent_impls_in_crate_query ( db : & dyn HirDatabase , krate : CrateId ) -> Arc < Self > {
272- let mut impls = Self { map : FxHashMap :: default ( ) } ;
273+ let mut impls = Self { map : FxHashMap :: default ( ) , invalid_impls : Vec :: default ( ) } ;
273274
274275 let crate_def_map = db. crate_def_map ( krate) ;
275276 impls. collect_def_map ( db, & crate_def_map) ;
@@ -282,7 +283,7 @@ impl InherentImpls {
282283 db : & dyn HirDatabase ,
283284 block : BlockId ,
284285 ) -> Option < Arc < Self > > {
285- let mut impls = Self { map : FxHashMap :: default ( ) } ;
286+ let mut impls = Self { map : FxHashMap :: default ( ) , invalid_impls : Vec :: default ( ) } ;
286287 if let Some ( block_def_map) = db. block_def_map ( block) {
287288 impls. collect_def_map ( db, & block_def_map) ;
288289 impls. shrink_to_fit ( ) ;
@@ -305,11 +306,17 @@ impl InherentImpls {
305306 }
306307
307308 let self_ty = db. impl_self_ty ( impl_id) ;
308- let fp = TyFingerprint :: for_inherent_impl ( self_ty. skip_binders ( ) ) ;
309- if let Some ( fp) = fp {
310- self . map . entry ( fp) . or_default ( ) . push ( impl_id) ;
309+ let self_ty = self_ty. skip_binders ( ) ;
310+
311+ match is_inherent_impl_coherent ( db, def_map, & data, self_ty) {
312+ true => {
313+ // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
314+ if let Some ( fp) = TyFingerprint :: for_inherent_impl ( self_ty) {
315+ self . map . entry ( fp) . or_default ( ) . push ( impl_id) ;
316+ }
317+ }
318+ false => self . invalid_impls . push ( impl_id) ,
311319 }
312- // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
313320 }
314321
315322 // To better support custom derives, collect impls in all unnamed const items.
@@ -333,6 +340,10 @@ impl InherentImpls {
333340 pub fn all_impls ( & self ) -> impl Iterator < Item = ImplId > + ' _ {
334341 self . map . values ( ) . flat_map ( |v| v. iter ( ) . copied ( ) )
335342 }
343+
344+ pub fn invalid_impls ( & self ) -> & [ ImplId ] {
345+ & self . invalid_impls
346+ }
336347}
337348
338349pub ( crate ) fn incoherent_inherent_impl_crates (
@@ -759,6 +770,90 @@ fn find_matching_impl(
759770 }
760771}
761772
773+ fn is_inherent_impl_coherent (
774+ db : & dyn HirDatabase ,
775+ def_map : & DefMap ,
776+ impl_data : & ImplData ,
777+ self_ty : & Ty ,
778+ ) -> bool {
779+ let self_ty = self_ty. kind ( Interner ) ;
780+ let impl_allowed = match self_ty {
781+ TyKind :: Tuple ( _, _)
782+ | TyKind :: FnDef ( _, _)
783+ | TyKind :: Array ( _, _)
784+ | TyKind :: Never
785+ | TyKind :: Raw ( _, _)
786+ | TyKind :: Ref ( _, _, _)
787+ | TyKind :: Slice ( _)
788+ | TyKind :: Str
789+ | TyKind :: Scalar ( _) => def_map. is_rustc_coherence_is_core ( ) ,
790+
791+ & TyKind :: Adt ( AdtId ( adt) , _) => adt. module ( db. upcast ( ) ) . krate ( ) == def_map. krate ( ) ,
792+ // FIXME: Factor out the principal trait fetching into a function
793+ TyKind :: Dyn ( it) => it
794+ . bounds
795+ . skip_binders ( )
796+ . interned ( )
797+ . get ( 0 )
798+ . and_then ( |b| match b. skip_binders ( ) {
799+ crate :: WhereClause :: Implemented ( trait_ref) => Some ( trait_ref) ,
800+ _ => None ,
801+ } )
802+ . map_or ( false , |trait_ref| {
803+ from_chalk_trait_id ( trait_ref. trait_id ) . module ( db. upcast ( ) ) . krate ( )
804+ == def_map. krate ( )
805+ } ) ,
806+
807+ _ => true ,
808+ } ;
809+ impl_allowed || {
810+ let rustc_has_incoherent_inherent_impls = match self_ty {
811+ TyKind :: Tuple ( _, _)
812+ | TyKind :: FnDef ( _, _)
813+ | TyKind :: Array ( _, _)
814+ | TyKind :: Never
815+ | TyKind :: Raw ( _, _)
816+ | TyKind :: Ref ( _, _, _)
817+ | TyKind :: Slice ( _)
818+ | TyKind :: Str
819+ | TyKind :: Scalar ( _) => true ,
820+
821+ & TyKind :: Adt ( AdtId ( adt) , _) => match adt {
822+ hir_def:: AdtId :: StructId ( it) => {
823+ db. struct_data ( it) . rustc_has_incoherent_inherent_impls
824+ }
825+ hir_def:: AdtId :: UnionId ( it) => {
826+ db. union_data ( it) . rustc_has_incoherent_inherent_impls
827+ }
828+ hir_def:: AdtId :: EnumId ( it) => db. enum_data ( it) . rustc_has_incoherent_inherent_impls ,
829+ } ,
830+ // FIXME: Factor out the principal trait fetching into a function
831+ TyKind :: Dyn ( it) => it
832+ . bounds
833+ . skip_binders ( )
834+ . interned ( )
835+ . get ( 0 )
836+ . and_then ( |b| match b. skip_binders ( ) {
837+ crate :: WhereClause :: Implemented ( trait_ref) => Some ( trait_ref) ,
838+ _ => None ,
839+ } )
840+ . map_or ( false , |trait_ref| {
841+ db. trait_data ( from_chalk_trait_id ( trait_ref. trait_id ) )
842+ . rustc_has_incoherent_inherent_impls
843+ } ) ,
844+
845+ _ => false ,
846+ } ;
847+ rustc_has_incoherent_inherent_impls
848+ && !impl_data. items . is_empty ( )
849+ && impl_data. items . iter ( ) . copied ( ) . all ( |assoc| match assoc {
850+ AssocItemId :: FunctionId ( it) => db. function_data ( it) . rustc_allow_incoherent_impl ,
851+ AssocItemId :: ConstId ( it) => db. const_data ( it) . rustc_allow_incoherent_impl ,
852+ AssocItemId :: TypeAliasId ( it) => db. type_alias_data ( it) . rustc_allow_incoherent_impl ,
853+ } )
854+ }
855+ }
856+
762857pub fn iterate_path_candidates (
763858 ty : & Canonical < Ty > ,
764859 db : & dyn HirDatabase ,
0 commit comments