@@ -12,6 +12,7 @@ use std::{
12
12
13
13
use either:: Either ;
14
14
use hir_def:: {
15
+ expr_store:: ExprOrPatSource ,
15
16
hir:: { Expr , ExprOrPatId } ,
16
17
lower:: LowerCtx ,
17
18
nameres:: { MacroSubNs , ModuleOrigin } ,
@@ -30,6 +31,7 @@ use hir_expand::{
30
31
name:: AsName ,
31
32
ExpandResult , FileRange , InMacroFile , MacroCallId , MacroFileId , MacroFileIdExt ,
32
33
} ;
34
+ use hir_ty:: diagnostics:: unsafe_operations_for_body;
33
35
use intern:: { sym, Symbol } ;
34
36
use itertools:: Itertools ;
35
37
use rustc_hash:: { FxHashMap , FxHashSet } ;
@@ -48,8 +50,8 @@ use crate::{
48
50
db:: HirDatabase ,
49
51
semantics:: source_to_def:: { ChildContainer , SourceToDefCache , SourceToDefCtx } ,
50
52
source_analyzer:: { name_hygiene, resolve_hir_path, SourceAnalyzer } ,
51
- Access , Adjust , Adjustment , Adt , AutoBorrow , BindingMode , BuiltinAttr , Callable , Const ,
52
- ConstParam , Crate , DeriveHelper , Enum , Field , Function , GenericSubstitution , HasSource ,
53
+ Adjust , Adjustment , Adt , AutoBorrow , BindingMode , BuiltinAttr , Callable , Const , ConstParam ,
54
+ Crate , DefWithBody , DeriveHelper , Enum , Field , Function , GenericSubstitution , HasSource ,
53
55
HirFileId , Impl , InFile , InlineAsmOperand , ItemInNs , Label , LifetimeParam , Local , Macro ,
54
56
Module , ModuleDef , Name , OverloadedDeref , Path , ScopeDef , Static , Struct , ToolModule , Trait ,
55
57
TraitAlias , TupleField , Type , TypeAlias , TypeParam , Union , Variant , VariantDef ,
@@ -1555,6 +1557,19 @@ impl<'db> SemanticsImpl<'db> {
1555
1557
. matched_arm
1556
1558
}
1557
1559
1560
+ pub fn get_unsafe_ops ( & self , def : DefWithBody ) -> FxHashSet < ExprOrPatSource > {
1561
+ let def = DefWithBodyId :: from ( def) ;
1562
+ let ( body, source_map) = self . db . body_with_source_map ( def) ;
1563
+ let infer = self . db . infer ( def) ;
1564
+ let mut res = FxHashSet :: default ( ) ;
1565
+ unsafe_operations_for_body ( self . db , & infer, def, & body, & mut |node| {
1566
+ if let Ok ( node) = source_map. expr_or_pat_syntax ( node) {
1567
+ res. insert ( node) ;
1568
+ }
1569
+ } ) ;
1570
+ res
1571
+ }
1572
+
1558
1573
pub fn is_unsafe_macro_call ( & self , macro_call : & ast:: MacroCall ) -> bool {
1559
1574
let Some ( mac) = self . resolve_macro_call ( macro_call) else { return false } ;
1560
1575
if mac. is_asm_or_global_asm ( self . db ) {
@@ -1682,6 +1697,15 @@ impl<'db> SemanticsImpl<'db> {
1682
1697
Some ( res)
1683
1698
}
1684
1699
1700
+ pub fn body_for ( & self , node : InFile < & SyntaxNode > ) -> Option < DefWithBody > {
1701
+ let container = self . with_ctx ( |ctx| ctx. find_container ( node) ) ?;
1702
+
1703
+ match container {
1704
+ ChildContainer :: DefWithBodyId ( def) => Some ( def. into ( ) ) ,
1705
+ _ => None ,
1706
+ }
1707
+ }
1708
+
1685
1709
/// Returns none if the file of the node is not part of a crate.
1686
1710
fn analyze ( & self , node : & SyntaxNode ) -> Option < SourceAnalyzer > {
1687
1711
let node = self . find_file ( node) ;
@@ -1783,91 +1807,6 @@ impl<'db> SemanticsImpl<'db> {
1783
1807
InFile :: new ( file_id, node)
1784
1808
}
1785
1809
1786
- pub fn is_unsafe_method_call ( & self , method_call_expr : & ast:: MethodCallExpr ) -> bool {
1787
- method_call_expr
1788
- . receiver ( )
1789
- . and_then ( |expr| {
1790
- let field_expr = match expr {
1791
- ast:: Expr :: FieldExpr ( field_expr) => field_expr,
1792
- _ => return None ,
1793
- } ;
1794
- let ty = self . type_of_expr ( & field_expr. expr ( ) ?) ?. original ;
1795
- if !ty. is_packed ( self . db ) {
1796
- return None ;
1797
- }
1798
-
1799
- let func = self . resolve_method_call ( method_call_expr) ?;
1800
- let res = match func. self_param ( self . db ) ?. access ( self . db ) {
1801
- Access :: Shared | Access :: Exclusive => true ,
1802
- Access :: Owned => false ,
1803
- } ;
1804
- Some ( res)
1805
- } )
1806
- . unwrap_or ( false )
1807
- }
1808
-
1809
- pub fn is_unsafe_ref_expr ( & self , ref_expr : & ast:: RefExpr ) -> bool {
1810
- ref_expr
1811
- . expr ( )
1812
- . and_then ( |expr| {
1813
- let field_expr = match expr {
1814
- ast:: Expr :: FieldExpr ( field_expr) => field_expr,
1815
- _ => return None ,
1816
- } ;
1817
- let expr = field_expr. expr ( ) ?;
1818
- self . type_of_expr ( & expr)
1819
- } )
1820
- // Binding a reference to a packed type is possibly unsafe.
1821
- . map ( |ty| ty. original . is_packed ( self . db ) )
1822
- . unwrap_or ( false )
1823
-
1824
- // FIXME This needs layout computation to be correct. It will highlight
1825
- // more than it should with the current implementation.
1826
- }
1827
-
1828
- pub fn is_unsafe_ident_pat ( & self , ident_pat : & ast:: IdentPat ) -> bool {
1829
- if ident_pat. ref_token ( ) . is_none ( ) {
1830
- return false ;
1831
- }
1832
-
1833
- ident_pat
1834
- . syntax ( )
1835
- . parent ( )
1836
- . and_then ( |parent| {
1837
- // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or
1838
- // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`,
1839
- // so this tries to lookup the `IdentPat` anywhere along that structure to the
1840
- // `RecordPat` so we can get the containing type.
1841
- let record_pat = ast:: RecordPatField :: cast ( parent. clone ( ) )
1842
- . and_then ( |record_pat| record_pat. syntax ( ) . parent ( ) )
1843
- . or_else ( || Some ( parent. clone ( ) ) )
1844
- . and_then ( |parent| {
1845
- ast:: RecordPatFieldList :: cast ( parent) ?
1846
- . syntax ( )
1847
- . parent ( )
1848
- . and_then ( ast:: RecordPat :: cast)
1849
- } ) ;
1850
-
1851
- // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
1852
- // this is initialized from a `FieldExpr`.
1853
- if let Some ( record_pat) = record_pat {
1854
- self . type_of_pat ( & ast:: Pat :: RecordPat ( record_pat) )
1855
- } else if let Some ( let_stmt) = ast:: LetStmt :: cast ( parent) {
1856
- let field_expr = match let_stmt. initializer ( ) ? {
1857
- ast:: Expr :: FieldExpr ( field_expr) => field_expr,
1858
- _ => return None ,
1859
- } ;
1860
-
1861
- self . type_of_expr ( & field_expr. expr ( ) ?)
1862
- } else {
1863
- None
1864
- }
1865
- } )
1866
- // Binding a reference to a packed type is possibly unsafe.
1867
- . map ( |ty| ty. original . is_packed ( self . db ) )
1868
- . unwrap_or ( false )
1869
- }
1870
-
1871
1810
/// Returns `true` if the `node` is inside an `unsafe` context.
1872
1811
pub fn is_inside_unsafe ( & self , expr : & ast:: Expr ) -> bool {
1873
1812
let Some ( enclosing_item) =
0 commit comments