@@ -4,7 +4,7 @@ mod injection;
44#[ cfg( test) ]
55mod tests;
66
7- use hir:: { Name , Semantics } ;
7+ use hir:: { Name , Semantics , VariantDef } ;
88use ra_ide_db:: {
99 defs:: { classify_name, classify_name_ref, Definition , NameClass , NameRefClass } ,
1010 RootDatabase ,
@@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
455455 Some ( TextRange :: new ( range_start, range_end) )
456456}
457457
458+ fn is_possibly_unsafe ( name_ref : & ast:: NameRef ) -> bool {
459+ name_ref
460+ . syntax ( )
461+ . parent ( )
462+ . and_then ( |parent| {
463+ ast:: FieldExpr :: cast ( parent. clone ( ) )
464+ . map ( |_| true )
465+ . or_else ( || ast:: RecordPatField :: cast ( parent) . map ( |_| true ) )
466+ } )
467+ . unwrap_or ( false )
468+ }
469+
458470fn highlight_element (
459471 sema : & Semantics < RootDatabase > ,
460472 bindings_shadow_count : & mut FxHashMap < Name , u32 > ,
@@ -484,10 +496,19 @@ fn highlight_element(
484496
485497 match name_kind {
486498 Some ( NameClass :: Definition ( def) ) => {
487- highlight_name ( db, def) | HighlightModifier :: Definition
499+ highlight_name ( db, def, false ) | HighlightModifier :: Definition
500+ }
501+ Some ( NameClass :: ConstReference ( def) ) => highlight_name ( db, def, false ) ,
502+ Some ( NameClass :: FieldShorthand { field, .. } ) => {
503+ let mut h = HighlightTag :: Field . into ( ) ;
504+ if let Definition :: Field ( field) = field {
505+ if let VariantDef :: Union ( _) = field. parent_def ( db) {
506+ h |= HighlightModifier :: Unsafe ;
507+ }
508+ }
509+
510+ h
488511 }
489- Some ( NameClass :: ConstReference ( def) ) => highlight_name ( db, def) ,
490- Some ( NameClass :: FieldShorthand { .. } ) => HighlightTag :: Field . into ( ) ,
491512 None => highlight_name_by_syntax ( name) | HighlightModifier :: Definition ,
492513 }
493514 }
@@ -498,6 +519,7 @@ fn highlight_element(
498519 }
499520 NAME_REF => {
500521 let name_ref = element. into_node ( ) . and_then ( ast:: NameRef :: cast) . unwrap ( ) ;
522+ let possibly_unsafe = is_possibly_unsafe ( & name_ref) ;
501523 match classify_name_ref ( sema, & name_ref) {
502524 Some ( name_kind) => match name_kind {
503525 NameRefClass :: Definition ( def) => {
@@ -508,11 +530,13 @@ fn highlight_element(
508530 binding_hash = Some ( calc_binding_hash ( & name, * shadow_count) )
509531 }
510532 } ;
511- highlight_name ( db, def)
533+ highlight_name ( db, def, possibly_unsafe )
512534 }
513535 NameRefClass :: FieldShorthand { .. } => HighlightTag :: Field . into ( ) ,
514536 } ,
515- None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax ( name_ref) ,
537+ None if syntactic_name_ref_highlighting => {
538+ highlight_name_ref_by_syntax ( name_ref, sema)
539+ }
516540 None => HighlightTag :: UnresolvedReference . into ( ) ,
517541 }
518542 }
@@ -652,10 +676,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
652676 }
653677}
654678
655- fn highlight_name ( db : & RootDatabase , def : Definition ) -> Highlight {
679+ fn highlight_name ( db : & RootDatabase , def : Definition , possibly_unsafe : bool ) -> Highlight {
656680 match def {
657681 Definition :: Macro ( _) => HighlightTag :: Macro ,
658- Definition :: Field ( _) => HighlightTag :: Field ,
682+ Definition :: Field ( field) => {
683+ let mut h = HighlightTag :: Field . into ( ) ;
684+ if possibly_unsafe {
685+ if let VariantDef :: Union ( _) = field. parent_def ( db) {
686+ h |= HighlightModifier :: Unsafe ;
687+ }
688+ }
689+
690+ return h;
691+ }
659692 Definition :: ModuleDef ( def) => match def {
660693 hir:: ModuleDef :: Module ( _) => HighlightTag :: Module ,
661694 hir:: ModuleDef :: Function ( func) => {
@@ -724,7 +757,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
724757 tag. into ( )
725758}
726759
727- fn highlight_name_ref_by_syntax ( name : ast:: NameRef ) -> Highlight {
760+ fn highlight_name_ref_by_syntax ( name : ast:: NameRef , sema : & Semantics < RootDatabase > ) -> Highlight {
728761 let default = HighlightTag :: UnresolvedReference ;
729762
730763 let parent = match name. syntax ( ) . parent ( ) {
@@ -734,7 +767,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight {
734767
735768 let tag = match parent. kind ( ) {
736769 METHOD_CALL_EXPR => HighlightTag :: Function ,
737- FIELD_EXPR => HighlightTag :: Field ,
770+ FIELD_EXPR => {
771+ let h = HighlightTag :: Field ;
772+ let is_union = ast:: FieldExpr :: cast ( parent)
773+ . and_then ( |field_expr| {
774+ let field = sema. resolve_field ( & field_expr) ?;
775+ Some ( if let VariantDef :: Union ( _) = field. parent_def ( sema. db ) {
776+ true
777+ } else {
778+ false
779+ } )
780+ } )
781+ . unwrap_or ( false ) ;
782+ return if is_union { h | HighlightModifier :: Unsafe } else { h. into ( ) } ;
783+ }
738784 PATH_SEGMENT => {
739785 let path = match parent. parent ( ) . and_then ( ast:: Path :: cast) {
740786 Some ( it) => it,
0 commit comments