@@ -19,7 +19,7 @@ use stdx::never;
1919use crate :: {
2020 autoderef:: { self , AutoderefKind } ,
2121 db:: HirDatabase ,
22- from_foreign_def_id,
22+ from_chalk_trait_id , from_foreign_def_id,
2323 infer:: { unify:: InferenceTable , Adjust , Adjustment , AutoBorrow , OverloadedDeref , PointerCast } ,
2424 primitive:: { FloatTy , IntTy , UintTy } ,
2525 static_lifetime, to_chalk_trait_id,
@@ -266,11 +266,12 @@ impl TraitImpls {
266266#[ derive( Debug , Eq , PartialEq ) ]
267267pub struct InherentImpls {
268268 map : FxHashMap < TyFingerprint , Vec < ImplId > > ,
269+ invalid_impls : Vec < ImplId > ,
269270}
270271
271272impl InherentImpls {
272273 pub ( crate ) fn inherent_impls_in_crate_query ( db : & dyn HirDatabase , krate : CrateId ) -> Arc < Self > {
273- let mut impls = Self { map : FxHashMap :: default ( ) } ;
274+ let mut impls = Self { map : FxHashMap :: default ( ) , invalid_impls : Vec :: default ( ) } ;
274275
275276 let crate_def_map = db. crate_def_map ( krate) ;
276277 impls. collect_def_map ( db, & crate_def_map) ;
@@ -283,7 +284,7 @@ impl InherentImpls {
283284 db : & dyn HirDatabase ,
284285 block : BlockId ,
285286 ) -> Option < Arc < Self > > {
286- let mut impls = Self { map : FxHashMap :: default ( ) } ;
287+ let mut impls = Self { map : FxHashMap :: default ( ) , invalid_impls : Vec :: default ( ) } ;
287288 if let Some ( block_def_map) = db. block_def_map ( block) {
288289 impls. collect_def_map ( db, & block_def_map) ;
289290 impls. shrink_to_fit ( ) ;
@@ -306,11 +307,17 @@ impl InherentImpls {
306307 }
307308
308309 let self_ty = db. impl_self_ty ( impl_id) ;
309- let fp = TyFingerprint :: for_inherent_impl ( self_ty. skip_binders ( ) ) ;
310- if let Some ( fp) = fp {
311- self . map . entry ( fp) . or_default ( ) . push ( impl_id) ;
310+ let self_ty = self_ty. skip_binders ( ) ;
311+
312+ match is_inherent_impl_coherent ( db, def_map, & data, self_ty) {
313+ true => {
314+ // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
315+ if let Some ( fp) = TyFingerprint :: for_inherent_impl ( self_ty) {
316+ self . map . entry ( fp) . or_default ( ) . push ( impl_id) ;
317+ }
318+ }
319+ false => self . invalid_impls . push ( impl_id) ,
312320 }
313- // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
314321 }
315322
316323 // To better support custom derives, collect impls in all unnamed const items.
@@ -334,6 +341,10 @@ impl InherentImpls {
334341 pub fn all_impls ( & self ) -> impl Iterator < Item = ImplId > + ' _ {
335342 self . map . values ( ) . flat_map ( |v| v. iter ( ) . copied ( ) )
336343 }
344+
345+ pub fn invalid_impls ( & self ) -> & [ ImplId ] {
346+ & self . invalid_impls
347+ }
337348}
338349
339350pub ( crate ) fn incoherent_inherent_impl_crates (
@@ -775,6 +786,90 @@ fn find_matching_impl(
775786 }
776787}
777788
789+ fn is_inherent_impl_coherent (
790+ db : & dyn HirDatabase ,
791+ def_map : & DefMap ,
792+ impl_data : & ImplData ,
793+ self_ty : & Ty ,
794+ ) -> bool {
795+ let self_ty = self_ty. kind ( Interner ) ;
796+ let impl_allowed = match self_ty {
797+ TyKind :: Tuple ( _, _)
798+ | TyKind :: FnDef ( _, _)
799+ | TyKind :: Array ( _, _)
800+ | TyKind :: Never
801+ | TyKind :: Raw ( _, _)
802+ | TyKind :: Ref ( _, _, _)
803+ | TyKind :: Slice ( _)
804+ | TyKind :: Str
805+ | TyKind :: Scalar ( _) => def_map. is_rustc_coherence_is_core ( ) ,
806+
807+ & TyKind :: Adt ( AdtId ( adt) , _) => adt. module ( db. upcast ( ) ) . krate ( ) == def_map. krate ( ) ,
808+ // FIXME: Factor out the principal trait fetching into a function
809+ TyKind :: Dyn ( it) => it
810+ . bounds
811+ . skip_binders ( )
812+ . interned ( )
813+ . get ( 0 )
814+ . and_then ( |b| match b. skip_binders ( ) {
815+ crate :: WhereClause :: Implemented ( trait_ref) => Some ( trait_ref) ,
816+ _ => None ,
817+ } )
818+ . map_or ( false , |trait_ref| {
819+ from_chalk_trait_id ( trait_ref. trait_id ) . module ( db. upcast ( ) ) . krate ( )
820+ == def_map. krate ( )
821+ } ) ,
822+
823+ _ => true ,
824+ } ;
825+ impl_allowed || {
826+ let rustc_has_incoherent_inherent_impls = match self_ty {
827+ TyKind :: Tuple ( _, _)
828+ | TyKind :: FnDef ( _, _)
829+ | TyKind :: Array ( _, _)
830+ | TyKind :: Never
831+ | TyKind :: Raw ( _, _)
832+ | TyKind :: Ref ( _, _, _)
833+ | TyKind :: Slice ( _)
834+ | TyKind :: Str
835+ | TyKind :: Scalar ( _) => true ,
836+
837+ & TyKind :: Adt ( AdtId ( adt) , _) => match adt {
838+ hir_def:: AdtId :: StructId ( it) => {
839+ db. struct_data ( it) . rustc_has_incoherent_inherent_impls
840+ }
841+ hir_def:: AdtId :: UnionId ( it) => {
842+ db. union_data ( it) . rustc_has_incoherent_inherent_impls
843+ }
844+ hir_def:: AdtId :: EnumId ( it) => db. enum_data ( it) . rustc_has_incoherent_inherent_impls ,
845+ } ,
846+ // FIXME: Factor out the principal trait fetching into a function
847+ TyKind :: Dyn ( it) => it
848+ . bounds
849+ . skip_binders ( )
850+ . interned ( )
851+ . get ( 0 )
852+ . and_then ( |b| match b. skip_binders ( ) {
853+ crate :: WhereClause :: Implemented ( trait_ref) => Some ( trait_ref) ,
854+ _ => None ,
855+ } )
856+ . map_or ( false , |trait_ref| {
857+ db. trait_data ( from_chalk_trait_id ( trait_ref. trait_id ) )
858+ . rustc_has_incoherent_inherent_impls
859+ } ) ,
860+
861+ _ => false ,
862+ } ;
863+ rustc_has_incoherent_inherent_impls
864+ && !impl_data. items . is_empty ( )
865+ && impl_data. items . iter ( ) . copied ( ) . all ( |assoc| match assoc {
866+ AssocItemId :: FunctionId ( it) => db. function_data ( it) . rustc_allow_incoherent_impl ,
867+ AssocItemId :: ConstId ( it) => db. const_data ( it) . rustc_allow_incoherent_impl ,
868+ AssocItemId :: TypeAliasId ( it) => db. type_alias_data ( it) . rustc_allow_incoherent_impl ,
869+ } )
870+ }
871+ }
872+
778873pub fn iterate_path_candidates (
779874 ty : & Canonical < Ty > ,
780875 db : & dyn HirDatabase ,
0 commit comments