@@ -5,11 +5,14 @@ mod source_to_def;
55use std:: { cell:: RefCell , fmt, iter, mem, ops} ;
66
77use base_db:: { FileId , FileRange } ;
8+ use either:: Either ;
89use hir_def:: {
9- body, macro_id_to_def_id,
10+ body,
11+ expr:: Expr ,
12+ macro_id_to_def_id,
1013 resolver:: { self , HasResolver , Resolver , TypeNs } ,
1114 type_ref:: Mutability ,
12- AsMacroCall , FunctionId , MacroId , TraitId , VariantId ,
15+ AsMacroCall , DefWithBodyId , FunctionId , MacroId , TraitId , VariantId ,
1316} ;
1417use hir_expand:: {
1518 db:: AstDatabase ,
@@ -438,8 +441,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
438441 }
439442
440443 pub fn to_def < T : ToDef > ( & self , src : & T ) -> Option < T :: Def > {
441- let src = self . imp . find_file ( src. syntax ( ) ) . with_value ( src) . cloned ( ) ;
442- T :: to_def ( & self . imp , src)
444+ self . imp . to_def ( src)
443445 }
444446
445447 pub fn to_module_def ( & self , file : FileId ) -> Option < Module > {
@@ -481,6 +483,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
481483 pub fn is_unsafe_ident_pat ( & self , ident_pat : & ast:: IdentPat ) -> bool {
482484 self . imp . is_unsafe_ident_pat ( ident_pat)
483485 }
486+
487+ /// Returns `true` if the `node` is inside an `unsafe` context.
488+ pub fn is_inside_unsafe ( & self , node : & SyntaxNode ) -> bool {
489+ self . imp . is_inside_unsafe ( node)
490+ }
484491}
485492
486493impl < ' db > SemanticsImpl < ' db > {
@@ -1243,6 +1250,11 @@ impl<'db> SemanticsImpl<'db> {
12431250 f ( & mut ctx)
12441251 }
12451252
1253+ fn to_def < T : ToDef > ( & self , src : & T ) -> Option < T :: Def > {
1254+ let src = self . find_file ( src. syntax ( ) ) . with_value ( src) . cloned ( ) ;
1255+ T :: to_def ( & self , src)
1256+ }
1257+
12461258 fn to_module_def ( & self , file : FileId ) -> impl Iterator < Item = Module > {
12471259 self . with_ctx ( |ctx| ctx. file_to_def ( file) ) . into_iter ( ) . map ( Module :: from)
12481260 }
@@ -1458,6 +1470,59 @@ impl<'db> SemanticsImpl<'db> {
14581470 . map ( |ty| ty. original . is_packed ( self . db ) )
14591471 . unwrap_or ( false )
14601472 }
1473+
1474+ fn is_inside_unsafe ( & self , node : & SyntaxNode ) -> bool {
1475+ let item_or_variant = |ancestor : SyntaxNode | {
1476+ if ast:: Item :: can_cast ( ancestor. kind ( ) ) {
1477+ ast:: Item :: cast ( ancestor) . map ( Either :: Left )
1478+ } else {
1479+ ast:: Variant :: cast ( ancestor) . map ( Either :: Right )
1480+ }
1481+ } ;
1482+ let Some ( enclosing_item) = node. ancestors ( ) . find_map ( item_or_variant) else { return false } ;
1483+
1484+ let def = match & enclosing_item {
1485+ Either :: Left ( ast:: Item :: Fn ( it) ) => {
1486+ self . to_def ( it) . map ( <_ >:: into) . map ( DefWithBodyId :: FunctionId )
1487+ }
1488+ Either :: Left ( ast:: Item :: Const ( it) ) => {
1489+ self . to_def ( it) . map ( <_ >:: into) . map ( DefWithBodyId :: ConstId )
1490+ }
1491+ Either :: Left ( ast:: Item :: Static ( it) ) => {
1492+ self . to_def ( it) . map ( <_ >:: into) . map ( DefWithBodyId :: StaticId )
1493+ }
1494+ Either :: Left ( _) => None ,
1495+ Either :: Right ( it) => self . to_def ( it) . map ( <_ >:: into) . map ( DefWithBodyId :: VariantId ) ,
1496+ } ;
1497+ let Some ( def) = def else { return false } ;
1498+ let enclosing_node = enclosing_item. as_ref ( ) . either ( |i| i. syntax ( ) , |v| v. syntax ( ) ) ;
1499+
1500+ if ast:: Fn :: cast ( enclosing_node. clone ( ) ) . and_then ( |f| f. unsafe_token ( ) ) . is_some ( ) {
1501+ return true ;
1502+ }
1503+
1504+ let ( body, source_map) = self . db . body_with_source_map ( def) ;
1505+
1506+ let file_id = self . find_file ( node) . file_id ;
1507+
1508+ let Some ( mut parent) = node. parent ( ) else { return false } ;
1509+ loop {
1510+ if & parent == enclosing_node {
1511+ break false ;
1512+ }
1513+
1514+ if let Some ( parent) = ast:: Expr :: cast ( parent. clone ( ) ) {
1515+ if let Some ( expr_id) = source_map. node_expr ( InFile { file_id, value : & parent } ) {
1516+ if let Expr :: Unsafe { .. } = body[ expr_id] {
1517+ break true ;
1518+ }
1519+ }
1520+ }
1521+
1522+ let Some ( parent_) = parent. parent ( ) else { break false } ;
1523+ parent = parent_;
1524+ }
1525+ }
14611526}
14621527
14631528fn macro_call_to_macro_id (
0 commit comments