diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-08-12 14:20:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-08-12 14:20:18 +0100 |
commit | 11de7ac2fb6514484076217acb8d93eb36468681 (patch) | |
tree | b727a8db741367634eebf4dc685e0f56fddb2a68 /crates/ra_ide/src | |
parent | 2d41cc0ea323e3c4d97300e4d66de11d6b7148ef (diff) | |
parent | 72baf1acdd544c645fd69c16967b91be9e75371b (diff) |
Merge #4743
4743: Add tracking of packed repr, use it to highlight unsafe refs r=matklad a=Nashenas88
Taking a reference to a misaligned field on a packed struct is an
unsafe operation. Highlight that behavior. Currently, the misaligned
part isn't tracked, so this highlight is a bit too aggressive.
Fixes #4600
Co-authored-by: Paul Daniel Faria <[email protected]>
Co-authored-by: Paul Daniel Faria <[email protected]>
Co-authored-by: Paul Daniel Faria <[email protected]>
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 89 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 33 |
2 files changed, 99 insertions, 23 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 6b7874460..c10e15db8 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -497,9 +497,9 @@ fn highlight_element( | |||
497 | match name_kind { | 497 | match name_kind { |
498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | 498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), |
499 | Some(NameClass::Definition(def)) => { | 499 | Some(NameClass::Definition(def)) => { |
500 | highlight_name(db, def, false) | HighlightModifier::Definition | 500 | highlight_name(sema, db, def, None, false) | HighlightModifier::Definition |
501 | } | 501 | } |
502 | Some(NameClass::ConstReference(def)) => highlight_name(db, def, false), | 502 | Some(NameClass::ConstReference(def)) => highlight_name(sema, db, def, None, false), |
503 | Some(NameClass::FieldShorthand { field, .. }) => { | 503 | Some(NameClass::FieldShorthand { field, .. }) => { |
504 | let mut h = HighlightTag::Field.into(); | 504 | let mut h = HighlightTag::Field.into(); |
505 | if let Definition::Field(field) = field { | 505 | if let Definition::Field(field) = field { |
@@ -532,7 +532,7 @@ fn highlight_element( | |||
532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
533 | } | 533 | } |
534 | }; | 534 | }; |
535 | highlight_name(db, def, possibly_unsafe) | 535 | highlight_name(sema, db, def, Some(name_ref), possibly_unsafe) |
536 | } | 536 | } |
537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
538 | }, | 538 | }, |
@@ -566,9 +566,20 @@ fn highlight_element( | |||
566 | } | 566 | } |
567 | } | 567 | } |
568 | p if p.is_punct() => match p { | 568 | p if p.is_punct() => match p { |
569 | T![::] | T![->] | T![=>] | T![&] | T![..] | T![=] | T![@] => { | 569 | T![&] => { |
570 | HighlightTag::Operator.into() | 570 | let h = HighlightTag::Operator.into(); |
571 | let is_unsafe = element | ||
572 | .parent() | ||
573 | .and_then(ast::RefExpr::cast) | ||
574 | .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)) | ||
575 | .unwrap_or(false); | ||
576 | if is_unsafe { | ||
577 | h | HighlightModifier::Unsafe | ||
578 | } else { | ||
579 | h | ||
580 | } | ||
571 | } | 581 | } |
582 | T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] => HighlightTag::Operator.into(), | ||
572 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { | 583 | T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => { |
573 | HighlightTag::Macro.into() | 584 | HighlightTag::Macro.into() |
574 | } | 585 | } |
@@ -649,6 +660,18 @@ fn highlight_element( | |||
649 | HighlightTag::SelfKeyword.into() | 660 | HighlightTag::SelfKeyword.into() |
650 | } | 661 | } |
651 | } | 662 | } |
663 | T![ref] => element | ||
664 | .parent() | ||
665 | .and_then(ast::IdentPat::cast) | ||
666 | .and_then(|ident_pat| { | ||
667 | if sema.is_unsafe_ident_pat(&ident_pat) { | ||
668 | Some(HighlightModifier::Unsafe) | ||
669 | } else { | ||
670 | None | ||
671 | } | ||
672 | }) | ||
673 | .map(|modifier| h | modifier) | ||
674 | .unwrap_or(h), | ||
652 | _ => h, | 675 | _ => h, |
653 | } | 676 | } |
654 | } | 677 | } |
@@ -678,7 +701,13 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
678 | } | 701 | } |
679 | } | 702 | } |
680 | 703 | ||
681 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { | 704 | fn highlight_name( |
705 | sema: &Semantics<RootDatabase>, | ||
706 | db: &RootDatabase, | ||
707 | def: Definition, | ||
708 | name_ref: Option<ast::NameRef>, | ||
709 | possibly_unsafe: bool, | ||
710 | ) -> Highlight { | ||
682 | match def { | 711 | match def { |
683 | Definition::Macro(_) => HighlightTag::Macro, | 712 | Definition::Macro(_) => HighlightTag::Macro, |
684 | Definition::Field(field) => { | 713 | Definition::Field(field) => { |
@@ -697,6 +726,15 @@ fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> | |||
697 | let mut h = HighlightTag::Function.into(); | 726 | let mut h = HighlightTag::Function.into(); |
698 | if func.is_unsafe(db) { | 727 | if func.is_unsafe(db) { |
699 | h |= HighlightModifier::Unsafe; | 728 | h |= HighlightModifier::Unsafe; |
729 | } else { | ||
730 | let is_unsafe = name_ref | ||
731 | .and_then(|name_ref| name_ref.syntax().parent()) | ||
732 | .and_then(ast::MethodCallExpr::cast) | ||
733 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
734 | .unwrap_or(false); | ||
735 | if is_unsafe { | ||
736 | h |= HighlightModifier::Unsafe; | ||
737 | } | ||
700 | } | 738 | } |
701 | return h; | 739 | return h; |
702 | } | 740 | } |
@@ -768,8 +806,18 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
768 | _ => return default.into(), | 806 | _ => return default.into(), |
769 | }; | 807 | }; |
770 | 808 | ||
771 | let tag = match parent.kind() { | 809 | match parent.kind() { |
772 | METHOD_CALL_EXPR => HighlightTag::Function, | 810 | METHOD_CALL_EXPR => { |
811 | let mut h = Highlight::new(HighlightTag::Function); | ||
812 | let is_unsafe = ast::MethodCallExpr::cast(parent) | ||
813 | .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) | ||
814 | .unwrap_or(false); | ||
815 | if is_unsafe { | ||
816 | h |= HighlightModifier::Unsafe; | ||
817 | } | ||
818 | |||
819 | h | ||
820 | } | ||
773 | FIELD_EXPR => { | 821 | FIELD_EXPR => { |
774 | let h = HighlightTag::Field; | 822 | let h = HighlightTag::Field; |
775 | let is_union = ast::FieldExpr::cast(parent) | 823 | let is_union = ast::FieldExpr::cast(parent) |
@@ -782,7 +830,11 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
782 | }) | 830 | }) |
783 | }) | 831 | }) |
784 | .unwrap_or(false); | 832 | .unwrap_or(false); |
785 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | 833 | if is_union { |
834 | h | HighlightModifier::Unsafe | ||
835 | } else { | ||
836 | h.into() | ||
837 | } | ||
786 | } | 838 | } |
787 | PATH_SEGMENT => { | 839 | PATH_SEGMENT => { |
788 | let path = match parent.parent().and_then(ast::Path::cast) { | 840 | let path = match parent.parent().and_then(ast::Path::cast) { |
@@ -807,18 +859,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
807 | }; | 859 | }; |
808 | 860 | ||
809 | match parent.kind() { | 861 | match parent.kind() { |
810 | CALL_EXPR => HighlightTag::Function, | 862 | CALL_EXPR => HighlightTag::Function.into(), |
811 | _ => { | 863 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
812 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | 864 | HighlightTag::Struct.into() |
813 | HighlightTag::Struct | 865 | } else { |
814 | } else { | 866 | HighlightTag::Constant |
815 | HighlightTag::Constant | ||
816 | } | ||
817 | } | 867 | } |
868 | .into(), | ||
818 | } | 869 | } |
819 | } | 870 | } |
820 | _ => default, | 871 | _ => default.into(), |
821 | }; | 872 | } |
822 | |||
823 | tag.into() | ||
824 | } | 873 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 09062c38e..a8087635a 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -292,10 +292,24 @@ struct TypeForStaticMut { | |||
292 | 292 | ||
293 | static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; | 293 | static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; |
294 | 294 | ||
295 | #[repr(packed)] | ||
296 | struct Packed { | ||
297 | a: u16, | ||
298 | } | ||
299 | |||
300 | trait DoTheAutoref { | ||
301 | fn calls_autoref(&self); | ||
302 | } | ||
303 | |||
304 | impl DoTheAutoref for u16 { | ||
305 | fn calls_autoref(&self) {} | ||
306 | } | ||
307 | |||
295 | fn main() { | 308 | fn main() { |
296 | let x = &5 as *const usize; | 309 | let x = &5 as *const _ as *const usize; |
297 | let u = Union { b: 0 }; | 310 | let u = Union { b: 0 }; |
298 | unsafe { | 311 | unsafe { |
312 | // unsafe fn and method calls | ||
299 | unsafe_fn(); | 313 | unsafe_fn(); |
300 | let b = u.b; | 314 | let b = u.b; |
301 | match u { | 315 | match u { |
@@ -303,9 +317,22 @@ fn main() { | |||
303 | Union { a } => (), | 317 | Union { a } => (), |
304 | } | 318 | } |
305 | HasUnsafeFn.unsafe_method(); | 319 | HasUnsafeFn.unsafe_method(); |
306 | let y = *(x); | 320 | |
307 | let z = -x; | 321 | // unsafe deref |
322 | let y = *x; | ||
323 | |||
324 | // unsafe access to a static mut | ||
308 | let a = global_mut.a; | 325 | let a = global_mut.a; |
326 | |||
327 | // unsafe ref of packed fields | ||
328 | let packed = Packed { a: 0 }; | ||
329 | let a = &packed.a; | ||
330 | let ref a = packed.a; | ||
331 | let Packed { ref a } = packed; | ||
332 | let Packed { a: ref _a } = packed; | ||
333 | |||
334 | // unsafe auto ref of packed field | ||
335 | packed.a.calls_autoref(); | ||
309 | } | 336 | } |
310 | } | 337 | } |
311 | "# | 338 | "# |