aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-12 14:20:18 +0100
committerGitHub <[email protected]>2020-08-12 14:20:18 +0100
commit11de7ac2fb6514484076217acb8d93eb36468681 (patch)
treeb727a8db741367634eebf4dc685e0f56fddb2a68 /crates
parent2d41cc0ea323e3c4d97300e4d66de11d6b7148ef (diff)
parent72baf1acdd544c645fd69c16967b91be9e75371b (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')
-rw-r--r--crates/ra_hir/src/code_model.rs18
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/semantics.rs99
-rw-r--r--crates/ra_hir_def/src/adt.rs42
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs89
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs33
-rw-r--r--crates/ra_ide/test_data/highlight_unsafe.html33
7 files changed, 284 insertions, 32 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 44456e49e..0007d7fa8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -4,6 +4,7 @@ use std::{iter, sync::Arc};
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use either::Either; 5use either::Either;
6use hir_def::{ 6use hir_def::{
7 adt::ReprKind,
7 adt::StructKind, 8 adt::StructKind,
8 adt::VariantData, 9 adt::VariantData,
9 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
@@ -431,6 +432,10 @@ impl Struct {
431 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) 432 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id)
432 } 433 }
433 434
435 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
436 db.struct_data(self.id).repr.clone()
437 }
438
434 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { 439 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
435 db.struct_data(self.id).variant_data.clone() 440 db.struct_data(self.id).variant_data.clone()
436 } 441 }
@@ -1253,6 +1258,19 @@ impl Type {
1253 ) 1258 )
1254 } 1259 }
1255 1260
1261 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1262 let adt_id = match self.ty.value {
1263 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id,
1264 _ => return false,
1265 };
1266
1267 let adt = adt_id.into();
1268 match adt {
1269 Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
1270 _ => false,
1271 }
1272 }
1273
1256 pub fn is_raw_ptr(&self) -> bool { 1274 pub fn is_raw_ptr(&self) -> bool {
1257 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) 1275 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
1258 } 1276 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 31f3241c9..34b02c536 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -49,7 +49,7 @@ pub use hir_def::{
49 docs::Documentation, 49 docs::Documentation,
50 nameres::ModuleSource, 50 nameres::ModuleSource,
51 path::{ModPath, Path, PathKind}, 51 path::{ModPath, Path, PathKind},
52 type_ref::Mutability, 52 type_ref::{Mutability, TypeRef},
53}; 53};
54pub use hir_expand::{ 54pub use hir_expand::{
55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, 55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index e392130ab..872f5fa4c 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -25,7 +25,8 @@ use crate::{
25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, 27 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef,
28 Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 28 Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef,
29 VariantDef,
29}; 30};
30use resolver::TypeNs; 31use resolver::TypeNs;
31 32
@@ -279,6 +280,18 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
279 pub fn assert_contains_node(&self, node: &SyntaxNode) { 280 pub fn assert_contains_node(&self, node: &SyntaxNode) {
280 self.imp.assert_contains_node(node) 281 self.imp.assert_contains_node(node)
281 } 282 }
283
284 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
285 self.imp.is_unsafe_method_call(method_call_expr)
286 }
287
288 pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
289 self.imp.is_unsafe_ref_expr(ref_expr)
290 }
291
292 pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
293 self.imp.is_unsafe_ident_pat(ident_pat)
294 }
282} 295}
283 296
284impl<'db> SemanticsImpl<'db> { 297impl<'db> SemanticsImpl<'db> {
@@ -574,6 +587,90 @@ impl<'db> SemanticsImpl<'db> {
574 }); 587 });
575 InFile::new(file_id, node) 588 InFile::new(file_id, node)
576 } 589 }
590
591 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
592 method_call_expr
593 .expr()
594 .and_then(|expr| {
595 let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr {
596 field_expr
597 } else {
598 return None;
599 };
600 let ty = self.type_of_expr(&field_expr.expr()?)?;
601 if !ty.is_packed(self.db) {
602 return None;
603 }
604
605 let func = self.resolve_method_call(&method_call_expr).map(Function::from)?;
606 let is_unsafe = func.has_self_param(self.db)
607 && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..)));
608 Some(is_unsafe)
609 })
610 .unwrap_or(false)
611 }
612
613 pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
614 ref_expr
615 .expr()
616 .and_then(|expr| {
617 let field_expr = match expr {
618 ast::Expr::FieldExpr(field_expr) => field_expr,
619 _ => return None,
620 };
621 let expr = field_expr.expr()?;
622 self.type_of_expr(&expr)
623 })
624 // Binding a reference to a packed type is possibly unsafe.
625 .map(|ty| ty.is_packed(self.db))
626 .unwrap_or(false)
627
628 // FIXME This needs layout computation to be correct. It will highlight
629 // more than it should with the current implementation.
630 }
631
632 pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
633 if !ident_pat.ref_token().is_some() {
634 return false;
635 }
636
637 ident_pat
638 .syntax()
639 .parent()
640 .and_then(|parent| {
641 // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or
642 // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`,
643 // so this tries to lookup the `IdentPat` anywhere along that structure to the
644 // `RecordPat` so we can get the containing type.
645 let record_pat = ast::RecordPatField::cast(parent.clone())
646 .and_then(|record_pat| record_pat.syntax().parent())
647 .or_else(|| Some(parent.clone()))
648 .and_then(|parent| {
649 ast::RecordPatFieldList::cast(parent)?
650 .syntax()
651 .parent()
652 .and_then(ast::RecordPat::cast)
653 });
654
655 // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
656 // this is initialized from a `FieldExpr`.
657 if let Some(record_pat) = record_pat {
658 self.type_of_pat(&ast::Pat::RecordPat(record_pat))
659 } else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
660 let field_expr = match let_stmt.initializer()? {
661 ast::Expr::FieldExpr(field_expr) => field_expr,
662 _ => return None,
663 };
664
665 self.type_of_expr(&field_expr.expr()?)
666 } else {
667 None
668 }
669 })
670 // Binding a reference to a packed type is possibly unsafe.
671 .map(|ty| ty.is_packed(self.db))
672 .unwrap_or(false)
673 }
577} 674}
578 675
579pub trait ToDef: AstNode + Clone { 676pub trait ToDef: AstNode + Clone {
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 6cb56a1cd..35c3a9140 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -9,11 +9,12 @@ use hir_expand::{
9}; 9};
10use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::{map::ArenaMap, Arena};
11use ra_syntax::ast::{self, NameOwner, VisibilityOwner}; 11use ra_syntax::ast::{self, NameOwner, VisibilityOwner};
12use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
12 13
13use crate::{ 14use crate::{
14 body::{CfgExpander, LowerCtx}, 15 body::{CfgExpander, LowerCtx},
15 db::DefDatabase, 16 db::DefDatabase,
16 item_tree::{Field, Fields, ItemTree}, 17 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem},
17 src::HasChildSource, 18 src::HasChildSource,
18 src::HasSource, 19 src::HasSource,
19 trace::Trace, 20 trace::Trace,
@@ -29,6 +30,7 @@ use ra_cfg::CfgOptions;
29pub struct StructData { 30pub struct StructData {
30 pub name: Name, 31 pub name: Name,
31 pub variant_data: Arc<VariantData>, 32 pub variant_data: Arc<VariantData>,
33 pub repr: Option<ReprKind>,
32} 34}
33 35
34#[derive(Debug, Clone, PartialEq, Eq)] 36#[derive(Debug, Clone, PartialEq, Eq)]
@@ -58,26 +60,58 @@ pub struct FieldData {
58 pub visibility: RawVisibility, 60 pub visibility: RawVisibility,
59} 61}
60 62
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub enum ReprKind {
65 Packed,
66 Other,
67}
68
69fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> {
70 item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt)
71}
72
73fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
74 match tt.delimiter {
75 Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
76 _ => return None,
77 }
78
79 let mut it = tt.token_trees.iter();
80 match it.next()? {
81 TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed),
82 _ => Some(ReprKind::Other),
83 }
84}
85
61impl StructData { 86impl StructData {
62 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 87 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
63 let loc = id.lookup(db); 88 let loc = id.lookup(db);
64 let item_tree = db.item_tree(loc.id.file_id); 89 let item_tree = db.item_tree(loc.id.file_id);
90 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
65 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 91 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
66 92
67 let strukt = &item_tree[loc.id.value]; 93 let strukt = &item_tree[loc.id.value];
68 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields); 94 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields);
69 95 Arc::new(StructData {
70 Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data) }) 96 name: strukt.name.clone(),
97 variant_data: Arc::new(variant_data),
98 repr,
99 })
71 } 100 }
72 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 101 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
73 let loc = id.lookup(db); 102 let loc = id.lookup(db);
74 let item_tree = db.item_tree(loc.id.file_id); 103 let item_tree = db.item_tree(loc.id.file_id);
104 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
75 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 105 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
76 106
77 let union = &item_tree[loc.id.value]; 107 let union = &item_tree[loc.id.value];
78 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields); 108 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields);
79 109
80 Arc::new(StructData { name: union.name.clone(), variant_data: Arc::new(variant_data) }) 110 Arc::new(StructData {
111 name: union.name.clone(),
112 variant_data: Arc::new(variant_data),
113 repr,
114 })
81 } 115 }
82} 116}
83 117
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
681fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { 704fn 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
293static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; 293static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 };
294 294
295#[repr(packed)]
296struct Packed {
297 a: u16,
298}
299
300trait DoTheAutoref {
301 fn calls_autoref(&self);
302}
303
304impl DoTheAutoref for u16 {
305 fn calls_autoref(&self) {}
306}
307
295fn main() { 308fn 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"#
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index 79409fe81..552fea668 100644
--- a/crates/ra_ide/test_data/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
@@ -54,10 +54,24 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
54 54
55<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> 55<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">global_mut</span><span class="punctuation">:</span> <span class="struct">TypeForStaticMut</span> <span class="operator">=</span> <span class="struct">TypeForStaticMut</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span>
56 56
57<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">repr</span><span class="punctuation">(</span><span class="attribute">packed</span><span class="punctuation">)</span><span class="attribute">]</span>
58<span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="punctuation">{</span>
59 <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u16</span><span class="punctuation">,</span>
60<span class="punctuation">}</span>
61
62<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span>
63 <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span>
64<span class="punctuation">}</span>
65
66<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span>
67 <span class="keyword">fn</span> <span class="function declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
68<span class="punctuation">}</span>
69
57<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> 70<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
58 <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> 71 <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span>
59 <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> 72 <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span>
60 <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> 73 <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span>
74 <span class="comment">// unsafe fn and method calls</span>
61 <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 75 <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
62 <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> 76 <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span>
63 <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> 77 <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span>
@@ -65,8 +79,21 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
65 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> 79 <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
66 <span class="punctuation">}</span> 80 <span class="punctuation">}</span>
67 <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 81 <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
68 <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span> 82
69 <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="variable">x</span><span class="punctuation">;</span> 83 <span class="comment">// unsafe deref</span>
84 <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span>
85
86 <span class="comment">// unsafe access to a static mut</span>
70 <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span> 87 <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="static mutable unsafe">global_mut</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span>
88
89 <span class="comment">// unsafe ref of packed fields</span>
90 <span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span>
91 <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span>
92 <span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">;</span>
93 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span>
94 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span>
95
96 <span class="comment">// unsafe auto ref of packed field</span>
97 <span class="variable">packed</span><span class="punctuation">.</span><span class="field">a</span><span class="punctuation">.</span><span class="function unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
71 <span class="punctuation">}</span> 98 <span class="punctuation">}</span>
72<span class="punctuation">}</span></code></pre> \ No newline at end of file 99<span class="punctuation">}</span></code></pre> \ No newline at end of file