@@ -53,10 +53,10 @@ use hir_def::{
5353 resolver:: { HasResolver , Resolver } ,
5454 src:: HasSource as _,
5555 AssocItemId , AssocItemLoc , AttrDefId , ConstId , ConstParamId , CrateRootModuleId , DefWithBodyId ,
56- EnumId , EnumVariantId , ExternCrateId , FunctionId , GenericDefId , HasModule , ImplId ,
57- InTypeConstId , ItemContainerId , LifetimeParamId , LocalEnumVariantId , LocalFieldId , Lookup ,
58- MacroExpander , MacroId , ModuleId , StaticId , StructId , TraitAliasId , TraitId , TypeAliasId ,
59- TypeOrConstParamId , TypeParamId , UnionId ,
56+ EnumId , EnumVariantId , ExternCrateId , FunctionId , GenericDefId , GenericParamId , HasModule ,
57+ ImplId , InTypeConstId , ItemContainerId , LifetimeParamId , LocalEnumVariantId , LocalFieldId ,
58+ Lookup , MacroExpander , MacroId , ModuleId , StaticId , StructId , TraitAliasId , TraitId ,
59+ TypeAliasId , TypeOrConstParamId , TypeParamId , UnionId ,
6060} ;
6161use hir_expand:: { name:: name, MacroCallKind } ;
6262use hir_ty:: {
@@ -89,17 +89,7 @@ use crate::db::{DefDatabase, HirDatabase};
8989
9090pub use crate :: {
9191 attrs:: { resolve_doc_path_on, HasAttrs } ,
92- diagnostics:: {
93- AnyDiagnostic , BreakOutsideOfLoop , CaseType , ExpectedFunction , InactiveCode ,
94- IncoherentImpl , IncorrectCase , InvalidDeriveTarget , MacroDefError , MacroError ,
95- MacroExpansionParseError , MalformedDerive , MismatchedArgCount ,
96- MismatchedTupleStructPatArgCount , MissingFields , MissingMatchArms , MissingUnsafe ,
97- MovedOutOfRef , NeedMut , NoSuchField , PrivateAssocItem , PrivateField ,
98- ReplaceFilterMapNextWithFindMap , TraitImplOrphan , TypeMismatch , TypedHole , UndeclaredLabel ,
99- UnimplementedBuiltinMacro , UnreachableLabel , UnresolvedExternCrate , UnresolvedField ,
100- UnresolvedImport , UnresolvedMacroCall , UnresolvedMethodCall , UnresolvedModule ,
101- UnresolvedProcMacro , UnusedMut , UnusedVariable ,
102- } ,
92+ diagnostics:: * ,
10393 has_source:: HasSource ,
10494 semantics:: { PathResolution , Semantics , SemanticsScope , TypeInfo , VisibleTraits } ,
10595} ;
@@ -613,22 +603,64 @@ impl Module {
613603 // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
614604 continue ;
615605 }
606+ let ast_id_map = db. ast_id_map ( file_id) ;
616607
617608 for diag in db. impl_data_with_diagnostics ( impl_def. id ) . 1 . iter ( ) {
618609 emit_def_diagnostic ( db, acc, diag) ;
619610 }
620611
621612 if inherent_impls. invalid_impls ( ) . contains ( & impl_def. id ) {
622- let ast_id_map = db. ast_id_map ( file_id) ;
623-
624613 acc. push ( IncoherentImpl { impl_ : ast_id_map. get ( node. ast_id ( ) ) , file_id } . into ( ) )
625614 }
626615
627616 if !impl_def. check_orphan_rules ( db) {
628- let ast_id_map = db. ast_id_map ( file_id) ;
629617 acc. push ( TraitImplOrphan { impl_ : ast_id_map. get ( node. ast_id ( ) ) , file_id } . into ( ) )
630618 }
631619
620+ let trait_ = impl_def. trait_ ( db) ;
621+ let trait_is_unsafe = trait_. map_or ( false , |t| t. is_unsafe ( db) ) ;
622+ let impl_is_negative = impl_def. is_negative ( db) ;
623+ let impl_is_unsafe = impl_def. is_unsafe ( db) ;
624+
625+ let drop_maybe_dangle = ( || {
626+ // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
627+ let trait_ = trait_?;
628+ let drop_trait = db. lang_item ( self . krate ( ) . into ( ) , LangItem :: Drop ) ?. as_trait ( ) ?;
629+ if drop_trait != trait_. into ( ) {
630+ return None ;
631+ }
632+ let parent = impl_def. id . into ( ) ;
633+ let generic_params = db. generic_params ( parent) ;
634+ let lifetime_params = generic_params. lifetimes . iter ( ) . map ( |( local_id, _) | {
635+ GenericParamId :: LifetimeParamId ( LifetimeParamId { parent, local_id } )
636+ } ) ;
637+ let type_params = generic_params
638+ . iter ( )
639+ . filter ( |( _, it) | it. type_param ( ) . is_some ( ) )
640+ . map ( |( local_id, _) | {
641+ GenericParamId :: TypeParamId ( TypeParamId :: from_unchecked (
642+ TypeOrConstParamId { parent, local_id } ,
643+ ) )
644+ } ) ;
645+ let res = type_params
646+ . chain ( lifetime_params)
647+ . any ( |p| db. attrs ( AttrDefId :: GenericParamId ( p) ) . by_key ( "may_dangle" ) . exists ( ) ) ;
648+ Some ( res)
649+ } ) ( )
650+ . unwrap_or ( false ) ;
651+
652+ match ( impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) {
653+ // unsafe negative impl
654+ ( true , _, true , _) |
655+ // unsafe impl for safe trait
656+ ( true , false , _, false ) => acc. push ( TraitImplIncorrectSafety { impl_ : ast_id_map. get ( node. ast_id ( ) ) , file_id, should_be_safe : true } . into ( ) ) ,
657+ // safe impl for unsafe trait
658+ ( false , true , false , _) |
659+ // safe impl of dangling drop
660+ ( false , false , _, true ) => acc. push ( TraitImplIncorrectSafety { impl_ : ast_id_map. get ( node. ast_id ( ) ) , file_id, should_be_safe : false } . into ( ) ) ,
661+ _ => ( ) ,
662+ } ;
663+
632664 for item in impl_def. items ( db) {
633665 let def: DefWithBody = match item {
634666 AssocItem :: Function ( it) => it. into ( ) ,
@@ -3404,7 +3436,7 @@ impl Impl {
34043436 }
34053437
34063438 pub fn is_unsafe ( self , db : & dyn HirDatabase ) -> bool {
3407- db. impl_data ( self . id ) . is_unique ( )
3439+ db. impl_data ( self . id ) . is_unsafe
34083440 }
34093441
34103442 pub fn module ( self , db : & dyn HirDatabase ) -> Module {
0 commit comments