diff options
author | Paul Daniel Faria <[email protected]> | 2020-06-27 22:11:43 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-08-10 13:44:54 +0100 |
commit | d5f11e530dbf6edbdd0ca32d6cd5fafe634c8c4a (patch) | |
tree | b348ea6d5552be08913ac3a451836cad5ac75c1a /crates | |
parent | 38440d53d8329ac9f3f2013c6e32b3f69b069c72 (diff) |
Unsafe borrow of packed fields: account for borrow through ref binding, auto ref function calls
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_trait_impl.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 137 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 31 |
10 files changed, 156 insertions, 48 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0007d7fa8..a880fa671 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | docs::Documentation, | 11 | docs::Documentation, |
12 | expr::{BindingAnnotation, Pat, PatId}, | 12 | expr::{BindingAnnotation, Pat, PatId}, |
13 | import_map, | 13 | import_map, |
14 | item_tree::SelfParam, | ||
14 | per_ns::PerNs, | 15 | per_ns::PerNs, |
15 | resolver::{HasResolver, Resolver}, | 16 | resolver::{HasResolver, Resolver}, |
16 | src::HasSource as _, | 17 | src::HasSource as _, |
@@ -670,8 +671,8 @@ impl Function { | |||
670 | db.function_data(self.id).name.clone() | 671 | db.function_data(self.id).name.clone() |
671 | } | 672 | } |
672 | 673 | ||
673 | pub fn has_self_param(self, db: &dyn HirDatabase) -> bool { | 674 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { |
674 | db.function_data(self.id).has_self_param | 675 | db.function_data(self.id).self_param |
675 | } | 676 | } |
676 | 677 | ||
677 | pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { | 678 | pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 88a8ef9bf..2a26b0183 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | attr::Attrs, | 10 | attr::Attrs, |
11 | body::Expander, | 11 | body::Expander, |
12 | db::DefDatabase, | 12 | db::DefDatabase, |
13 | item_tree::{AssocItem, ItemTreeId, ModItem}, | 13 | item_tree::{AssocItem, ItemTreeId, ModItem, SelfParam}, |
14 | type_ref::{TypeBound, TypeRef}, | 14 | type_ref::{TypeBound, TypeRef}, |
15 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -25,7 +25,7 @@ pub struct FunctionData { | |||
25 | pub attrs: Attrs, | 25 | pub attrs: Attrs, |
26 | /// True if the first param is `self`. This is relevant to decide whether this | 26 | /// True if the first param is `self`. This is relevant to decide whether this |
27 | /// can be called as a method. | 27 | /// can be called as a method. |
28 | pub has_self_param: bool, | 28 | pub self_param: Option<SelfParam>, |
29 | pub is_unsafe: bool, | 29 | pub is_unsafe: bool, |
30 | pub is_varargs: bool, | 30 | pub is_varargs: bool, |
31 | pub visibility: RawVisibility, | 31 | pub visibility: RawVisibility, |
@@ -42,7 +42,7 @@ impl FunctionData { | |||
42 | params: func.params.to_vec(), | 42 | params: func.params.to_vec(), |
43 | ret_type: func.ret_type.clone(), | 43 | ret_type: func.ret_type.clone(), |
44 | attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), | 44 | attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), |
45 | has_self_param: func.has_self_param, | 45 | self_param: func.self_param, |
46 | is_unsafe: func.is_unsafe, | 46 | is_unsafe: func.is_unsafe, |
47 | is_varargs: func.is_varargs, | 47 | is_varargs: func.is_varargs, |
48 | visibility: item_tree[func.visibility].clone(), | 48 | visibility: item_tree[func.visibility].clone(), |
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index a67e75dac..1eaea66e4 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -500,7 +500,7 @@ pub struct Function { | |||
500 | pub name: Name, | 500 | pub name: Name, |
501 | pub visibility: RawVisibilityId, | 501 | pub visibility: RawVisibilityId, |
502 | pub generic_params: GenericParamsId, | 502 | pub generic_params: GenericParamsId, |
503 | pub has_self_param: bool, | 503 | pub self_param: Option<SelfParam>, |
504 | pub is_unsafe: bool, | 504 | pub is_unsafe: bool, |
505 | pub params: Box<[TypeRef]>, | 505 | pub params: Box<[TypeRef]>, |
506 | pub is_varargs: bool, | 506 | pub is_varargs: bool, |
@@ -508,6 +508,12 @@ pub struct Function { | |||
508 | pub ast_id: FileAstId<ast::Fn>, | 508 | pub ast_id: FileAstId<ast::Fn>, |
509 | } | 509 | } |
510 | 510 | ||
511 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
512 | pub struct SelfParam { | ||
513 | pub is_ref: bool, | ||
514 | pub is_mut: bool, | ||
515 | } | ||
516 | |||
511 | #[derive(Debug, Clone, Eq, PartialEq)] | 517 | #[derive(Debug, Clone, Eq, PartialEq)] |
512 | pub struct Struct { | 518 | pub struct Struct { |
513 | pub name: Name, | 519 | pub name: Name, |
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 450ef8798..89ad91d37 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -283,7 +283,7 @@ impl Ctx { | |||
283 | let name = func.name()?.as_name(); | 283 | let name = func.name()?.as_name(); |
284 | 284 | ||
285 | let mut params = Vec::new(); | 285 | let mut params = Vec::new(); |
286 | let mut has_self_param = false; | 286 | let mut func_self_param = None; |
287 | if let Some(param_list) = func.param_list() { | 287 | if let Some(param_list) = func.param_list() { |
288 | if let Some(self_param) = param_list.self_param() { | 288 | if let Some(self_param) = param_list.self_param() { |
289 | let self_type = match self_param.ty() { | 289 | let self_type = match self_param.ty() { |
@@ -302,7 +302,10 @@ impl Ctx { | |||
302 | } | 302 | } |
303 | }; | 303 | }; |
304 | params.push(self_type); | 304 | params.push(self_type); |
305 | has_self_param = true; | 305 | func_self_param = Some(SelfParam { |
306 | is_ref: self_param.amp_token().is_some(), | ||
307 | is_mut: self_param.mut_token().is_some(), | ||
308 | }); | ||
306 | } | 309 | } |
307 | for param in param_list.params() { | 310 | for param in param_list.params() { |
308 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); | 311 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); |
@@ -335,7 +338,7 @@ impl Ctx { | |||
335 | name, | 338 | name, |
336 | visibility, | 339 | visibility, |
337 | generic_params: GenericParamsId::EMPTY, | 340 | generic_params: GenericParamsId::EMPTY, |
338 | has_self_param, | 341 | self_param: func_self_param, |
339 | is_unsafe: func.unsafe_token().is_some(), | 342 | is_unsafe: func.unsafe_token().is_some(), |
340 | params: params.into_boxed_slice(), | 343 | params: params.into_boxed_slice(), |
341 | is_varargs, | 344 | is_varargs, |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index fb4b30a13..79c5adf0f 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -640,7 +640,7 @@ fn is_valid_candidate( | |||
640 | } | 640 | } |
641 | } | 641 | } |
642 | if let Some(receiver_ty) = receiver_ty { | 642 | if let Some(receiver_ty) = receiver_ty { |
643 | if !data.has_self_param { | 643 | if data.self_param.is_none() { |
644 | return false; | 644 | return false; |
645 | } | 645 | } |
646 | let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { | 646 | let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 532665285..5488db43f 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -48,7 +48,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
48 | let mut seen_methods = FxHashSet::default(); | 48 | let mut seen_methods = FxHashSet::default(); |
49 | let traits_in_scope = ctx.scope.traits_in_scope(); | 49 | let traits_in_scope = ctx.scope.traits_in_scope(); |
50 | receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { | 50 | receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { |
51 | if func.has_self_param(ctx.db) | 51 | if func.self_param(ctx.db).is_some() |
52 | && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m)) | 52 | && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m)) |
53 | && seen_methods.insert(func.name(ctx.db)) | 53 | && seen_methods.insert(func.name(ctx.db)) |
54 | { | 54 | { |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index d9a0ef167..e3ba7ebc4 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -136,7 +136,7 @@ fn add_function_impl( | |||
136 | .lookup_by(fn_name) | 136 | .lookup_by(fn_name) |
137 | .set_documentation(func.docs(ctx.db)); | 137 | .set_documentation(func.docs(ctx.db)); |
138 | 138 | ||
139 | let completion_kind = if func.has_self_param(ctx.db) { | 139 | let completion_kind = if func.self_param(ctx.db).is_some() { |
140 | CompletionItemKind::Method | 140 | CompletionItemKind::Method |
141 | } else { | 141 | } else { |
142 | CompletionItemKind::Function | 142 | CompletionItemKind::Function |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 9a94ff476..fc3d1a4bd 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -191,7 +191,7 @@ impl Completions { | |||
191 | func: hir::Function, | 191 | func: hir::Function, |
192 | local_name: Option<String>, | 192 | local_name: Option<String>, |
193 | ) { | 193 | ) { |
194 | let has_self_param = func.has_self_param(ctx.db); | 194 | let has_self_param = func.self_param(ctx.db).is_some(); |
195 | 195 | ||
196 | let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); | 196 | let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); |
197 | let ast_node = func.source(ctx.db).value; | 197 | let ast_node = func.source(ctx.db).value; |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index a4a7aa228..454fef39c 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 | }, |
@@ -565,8 +565,8 @@ fn highlight_element( | |||
565 | _ => h, | 565 | _ => h, |
566 | } | 566 | } |
567 | } | 567 | } |
568 | REF_EXPR => { | 568 | T![&] => { |
569 | let ref_expr = element.into_node().and_then(ast::RefExpr::cast)?; | 569 | let ref_expr = element.parent().and_then(ast::RefExpr::cast)?; |
570 | let expr = ref_expr.expr()?; | 570 | let expr = ref_expr.expr()?; |
571 | let field_expr = match expr { | 571 | let field_expr = match expr { |
572 | ast::Expr::FieldExpr(fe) => fe, | 572 | ast::Expr::FieldExpr(fe) => fe, |
@@ -668,6 +668,52 @@ fn highlight_element( | |||
668 | HighlightTag::SelfKeyword.into() | 668 | HighlightTag::SelfKeyword.into() |
669 | } | 669 | } |
670 | } | 670 | } |
671 | T![ref] => { | ||
672 | let modifier: Option<HighlightModifier> = (|| { | ||
673 | let bind_pat = element.parent().and_then(ast::BindPat::cast)?; | ||
674 | let parent = bind_pat.syntax().parent()?; | ||
675 | |||
676 | let ty = if let Some(pat_list) = | ||
677 | ast::RecordFieldPatList::cast(parent.clone()) | ||
678 | { | ||
679 | let record_pat = | ||
680 | pat_list.syntax().parent().and_then(ast::RecordPat::cast)?; | ||
681 | sema.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
682 | } else if let Some(let_stmt) = ast::LetStmt::cast(parent.clone()) { | ||
683 | let field_expr = | ||
684 | if let ast::Expr::FieldExpr(field_expr) = let_stmt.initializer()? { | ||
685 | field_expr | ||
686 | } else { | ||
687 | return None; | ||
688 | }; | ||
689 | |||
690 | sema.type_of_expr(&field_expr.expr()?) | ||
691 | } else if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent) { | ||
692 | let record_pat = record_field_pat | ||
693 | .syntax() | ||
694 | .parent() | ||
695 | .and_then(ast::RecordFieldPatList::cast)? | ||
696 | .syntax() | ||
697 | .parent() | ||
698 | .and_then(ast::RecordPat::cast)?; | ||
699 | sema.type_of_pat(&ast::Pat::RecordPat(record_pat)) | ||
700 | } else { | ||
701 | None | ||
702 | }?; | ||
703 | |||
704 | if !ty.is_packed(db) { | ||
705 | return None; | ||
706 | } | ||
707 | |||
708 | Some(HighlightModifier::Unsafe) | ||
709 | })(); | ||
710 | |||
711 | if let Some(modifier) = modifier { | ||
712 | h | modifier | ||
713 | } else { | ||
714 | h | ||
715 | } | ||
716 | } | ||
671 | _ => h, | 717 | _ => h, |
672 | } | 718 | } |
673 | } | 719 | } |
@@ -697,7 +743,13 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
697 | } | 743 | } |
698 | } | 744 | } |
699 | 745 | ||
700 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { | 746 | fn highlight_name( |
747 | sema: &Semantics<RootDatabase>, | ||
748 | db: &RootDatabase, | ||
749 | def: Definition, | ||
750 | name_ref: Option<ast::NameRef>, | ||
751 | possibly_unsafe: bool, | ||
752 | ) -> Highlight { | ||
701 | match def { | 753 | match def { |
702 | Definition::Macro(_) => HighlightTag::Macro, | 754 | Definition::Macro(_) => HighlightTag::Macro, |
703 | Definition::Field(field) => { | 755 | Definition::Field(field) => { |
@@ -716,6 +768,29 @@ fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> | |||
716 | let mut h = HighlightTag::Function.into(); | 768 | let mut h = HighlightTag::Function.into(); |
717 | if func.is_unsafe(db) { | 769 | if func.is_unsafe(db) { |
718 | h |= HighlightModifier::Unsafe; | 770 | h |= HighlightModifier::Unsafe; |
771 | } else { | ||
772 | (|| { | ||
773 | let method_call_expr = | ||
774 | name_ref?.syntax().parent().and_then(ast::MethodCallExpr::cast)?; | ||
775 | let expr = method_call_expr.expr()?; | ||
776 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
777 | Some(field_expr) | ||
778 | } else { | ||
779 | None | ||
780 | }?; | ||
781 | let ty = sema.type_of_expr(&field_expr.expr()?)?; | ||
782 | if !ty.is_packed(db) { | ||
783 | return None; | ||
784 | } | ||
785 | |||
786 | let func = sema.resolve_method_call(&method_call_expr)?; | ||
787 | if func.self_param(db)?.is_ref { | ||
788 | Some(HighlightModifier::Unsafe) | ||
789 | } else { | ||
790 | None | ||
791 | } | ||
792 | })() | ||
793 | .map(|modifier| h |= modifier); | ||
719 | } | 794 | } |
720 | return h; | 795 | return h; |
721 | } | 796 | } |
@@ -787,8 +862,33 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
787 | _ => return default.into(), | 862 | _ => return default.into(), |
788 | }; | 863 | }; |
789 | 864 | ||
790 | let tag = match parent.kind() { | 865 | match parent.kind() { |
791 | METHOD_CALL_EXPR => HighlightTag::Function, | 866 | METHOD_CALL_EXPR => { |
867 | let mut h = Highlight::new(HighlightTag::Function); | ||
868 | let modifier: Option<HighlightModifier> = (|| { | ||
869 | let method_call_expr = ast::MethodCallExpr::cast(parent)?; | ||
870 | let expr = method_call_expr.expr()?; | ||
871 | let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { | ||
872 | field_expr | ||
873 | } else { | ||
874 | return None; | ||
875 | }; | ||
876 | |||
877 | let expr = field_expr.expr()?; | ||
878 | let ty = sema.type_of_expr(&expr)?; | ||
879 | if ty.is_packed(sema.db) { | ||
880 | Some(HighlightModifier::Unsafe) | ||
881 | } else { | ||
882 | None | ||
883 | } | ||
884 | })(); | ||
885 | |||
886 | if let Some(modifier) = modifier { | ||
887 | h |= modifier; | ||
888 | } | ||
889 | |||
890 | h | ||
891 | } | ||
792 | FIELD_EXPR => { | 892 | FIELD_EXPR => { |
793 | let h = HighlightTag::Field; | 893 | let h = HighlightTag::Field; |
794 | let is_union = ast::FieldExpr::cast(parent) | 894 | let is_union = ast::FieldExpr::cast(parent) |
@@ -801,7 +901,7 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
801 | }) | 901 | }) |
802 | }) | 902 | }) |
803 | .unwrap_or(false); | 903 | .unwrap_or(false); |
804 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | 904 | if is_union { h | HighlightModifier::Unsafe } else { h.into() } |
805 | } | 905 | } |
806 | PATH_SEGMENT => { | 906 | PATH_SEGMENT => { |
807 | let path = match parent.parent().and_then(ast::Path::cast) { | 907 | let path = match parent.parent().and_then(ast::Path::cast) { |
@@ -826,18 +926,15 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas | |||
826 | }; | 926 | }; |
827 | 927 | ||
828 | match parent.kind() { | 928 | match parent.kind() { |
829 | CALL_EXPR => HighlightTag::Function, | 929 | CALL_EXPR => HighlightTag::Function.into(), |
830 | _ => { | 930 | _ => if name.text().chars().next().unwrap_or_default().is_uppercase() { |
831 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | 931 | HighlightTag::Struct.into() |
832 | HighlightTag::Struct | 932 | } else { |
833 | } else { | 933 | HighlightTag::Constant |
834 | HighlightTag::Constant | ||
835 | } | ||
836 | } | 934 | } |
935 | .into(), | ||
837 | } | 936 | } |
838 | } | 937 | } |
839 | _ => default, | 938 | _ => default.into(), |
840 | }; | 939 | } |
841 | |||
842 | tag.into() | ||
843 | } | 940 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index a7f5ad862..a8087635a 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -301,16 +301,7 @@ trait DoTheAutoref { | |||
301 | fn calls_autoref(&self); | 301 | fn calls_autoref(&self); |
302 | } | 302 | } |
303 | 303 | ||
304 | struct NeedsAlign { | 304 | impl DoTheAutoref for u16 { |
305 | a: u16 | ||
306 | } | ||
307 | |||
308 | #[repr(packed)] | ||
309 | struct HasAligned { | ||
310 | a: NeedsAlign | ||
311 | } | ||
312 | |||
313 | impl DoTheAutoref for NeedsAlign { | ||
314 | fn calls_autoref(&self) {} | 305 | fn calls_autoref(&self) {} |
315 | } | 306 | } |
316 | 307 | ||
@@ -318,6 +309,7 @@ fn main() { | |||
318 | let x = &5 as *const _ as *const usize; | 309 | let x = &5 as *const _ as *const usize; |
319 | let u = Union { b: 0 }; | 310 | let u = Union { b: 0 }; |
320 | unsafe { | 311 | unsafe { |
312 | // unsafe fn and method calls | ||
321 | unsafe_fn(); | 313 | unsafe_fn(); |
322 | let b = u.b; | 314 | let b = u.b; |
323 | match u { | 315 | match u { |
@@ -325,13 +317,22 @@ fn main() { | |||
325 | Union { a } => (), | 317 | Union { a } => (), |
326 | } | 318 | } |
327 | HasUnsafeFn.unsafe_method(); | 319 | HasUnsafeFn.unsafe_method(); |
328 | let _y = *(x); | 320 | |
329 | let z = -x; | 321 | // unsafe deref |
322 | let y = *x; | ||
323 | |||
324 | // unsafe access to a static mut | ||
330 | let a = global_mut.a; | 325 | let a = global_mut.a; |
326 | |||
327 | // unsafe ref of packed fields | ||
331 | let packed = Packed { a: 0 }; | 328 | let packed = Packed { a: 0 }; |
332 | let _a = &packed.a; | 329 | let a = &packed.a; |
333 | let h = HasAligned{ a: NeedsAlign { a: 1 } }; | 330 | let ref a = packed.a; |
334 | h.a.calls_autoref(); | 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(); | ||
335 | } | 336 | } |
336 | } | 337 | } |
337 | "# | 338 | "# |