aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/adt.rs
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/ra_hir_def/src/adt.rs
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/ra_hir_def/src/adt.rs')
-rw-r--r--crates/ra_hir_def/src/adt.rs42
1 files changed, 38 insertions, 4 deletions
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