aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs15
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir/src/semantics.rs50
-rw-r--r--crates/ide/src/syntax_highlighting.rs117
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs39
-rw-r--r--crates/ide/test_data/highlighting.html41
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
9 files changed, 220 insertions, 49 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index c442654dd..31d5276b0 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -670,6 +670,21 @@ impl Function {
670 db.function_data(self.id).has_self_param 670 db.function_data(self.id).has_self_param
671 } 671 }
672 672
673 pub fn mutability_of_self_param(self, db: &dyn HirDatabase) -> Option<Mutability> {
674 let func_data = db.function_data(self.id);
675 if !func_data.has_self_param {
676 return None;
677 }
678
679 func_data.params.first().and_then(|param| {
680 if let TypeRef::Reference(_, mutability) = param {
681 Some(*mutability)
682 } else {
683 None
684 }
685 })
686 }
687
673 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { 688 pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> {
674 db.function_data(self.id).params.clone() 689 db.function_data(self.id).params.clone()
675 } 690 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8961ba8fd..fc1c1ccd3 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -38,7 +38,7 @@ pub use crate::{
38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
39 }, 39 },
40 has_source::HasSource, 40 has_source::HasSource,
41 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope},
42}; 42};
43 43
44pub use hir_def::{ 44pub use hir_def::{
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index c693176fa..aff0e73da 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -6,8 +6,10 @@ use std::{cell::RefCell, fmt, iter::successors};
6 6
7use base_db::{FileId, FileRange}; 7use base_db::{FileId, FileRange};
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget,
9 resolver::{self, HasResolver, Resolver, TypeNs}, 10 resolver::{self, HasResolver, Resolver, TypeNs},
10 AsMacroCall, FunctionId, TraitId, VariantId, 11 src::HasSource,
12 AsMacroCall, FunctionId, Lookup, TraitId, VariantId,
11}; 13};
12use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; 14use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
13use hir_ty::associated_type_shorthand_candidates; 15use hir_ty::associated_type_shorthand_candidates;
@@ -15,7 +17,7 @@ use itertools::Itertools;
15use rustc_hash::{FxHashMap, FxHashSet}; 17use rustc_hash::{FxHashMap, FxHashSet};
16use syntax::{ 18use syntax::{
17 algo::{find_node_at_offset, skip_trivia_token}, 19 algo::{find_node_at_offset, skip_trivia_token},
18 ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, 20 ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize,
19}; 21};
20 22
21use crate::{ 23use crate::{
@@ -79,6 +81,13 @@ impl PathResolution {
79 } 81 }
80} 82}
81 83
84pub enum SelfKind {
85 Shared,
86 Mutable,
87 Consuming,
88 Copied,
89}
90
82/// Primary API to get semantic information, like types, from syntax trees. 91/// Primary API to get semantic information, like types, from syntax trees.
83pub struct Semantics<'db, DB> { 92pub struct Semantics<'db, DB> {
84 pub db: &'db DB, 93 pub db: &'db DB,
@@ -188,6 +197,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
188 self.imp.type_of_self(param) 197 self.imp.type_of_self(param)
189 } 198 }
190 199
200 pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
201 self.imp.method_receiver_kind(call)
202 }
203
191 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 204 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
192 self.imp.resolve_method_call(call).map(Function::from) 205 self.imp.resolve_method_call(call).map(Function::from)
193 } 206 }
@@ -267,7 +280,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
267 self.imp.assert_contains_node(node) 280 self.imp.assert_contains_node(node)
268 } 281 }
269 282
270 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { 283 pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
271 self.imp.is_unsafe_method_call(method_call_expr) 284 self.imp.is_unsafe_method_call(method_call_expr)
272 } 285 }
273 286
@@ -410,6 +423,35 @@ impl<'db> SemanticsImpl<'db> {
410 self.analyze(param.syntax()).type_of_self(self.db, &param) 423 self.analyze(param.syntax()).type_of_self(self.db, &param)
411 } 424 }
412 425
426 fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
427 self.resolve_method_call(call).and_then(|func| {
428 let lookup = func.lookup(self.db.upcast());
429 let src = lookup.source(self.db.upcast());
430 let param_list = src.value.param_list()?;
431 let self_param = param_list.self_param()?;
432 if self_param.amp_token().is_some() {
433 return Some(if self_param.mut_token().is_some() {
434 SelfKind::Mutable
435 } else {
436 SelfKind::Shared
437 });
438 }
439
440 let ty = self.type_of_expr(&call.expr()?)?;
441 let krate = Function::from(func).krate(self.db)?;
442 let lang_item = self.db.lang_item(krate.id, SmolStr::new("copy"));
443 let copy_trait = match lang_item? {
444 LangItemTarget::TraitId(copy_trait) => Trait::from(copy_trait),
445 _ => return None,
446 };
447 Some(if ty.impls_trait(self.db, copy_trait, &[]) {
448 SelfKind::Copied
449 } else {
450 SelfKind::Consuming
451 })
452 })
453 }
454
413 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 455 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
414 self.analyze(call.syntax()).resolve_method_call(self.db, call) 456 self.analyze(call.syntax()).resolve_method_call(self.db, call)
415 } 457 }
@@ -571,7 +613,7 @@ impl<'db> SemanticsImpl<'db> {
571 InFile::new(file_id, node) 613 InFile::new(file_id, node)
572 } 614 }
573 615
574 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { 616 pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
575 method_call_expr 617 method_call_expr
576 .expr() 618 .expr()
577 .and_then(|expr| { 619 .and_then(|expr| {
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 5d7c7e8d0..9827c68af 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -4,7 +4,7 @@ mod injection;
4#[cfg(test)] 4#[cfg(test)]
5mod tests; 5mod tests;
6 6
7use hir::{Name, Semantics, VariantDef}; 7use hir::{Mutability, Name, SelfKind, Semantics, VariantDef};
8use ide_db::{ 8use ide_db::{
9 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, 9 defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
10 RootDatabase, 10 RootDatabase,
@@ -519,27 +519,29 @@ fn highlight_element(
519 } 519 }
520 NAME_REF => { 520 NAME_REF => {
521 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 521 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
522 let possibly_unsafe = is_possibly_unsafe(&name_ref); 522 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
523 match classify_name_ref(sema, &name_ref) { 523 let possibly_unsafe = is_possibly_unsafe(&name_ref);
524 Some(name_kind) => match name_kind { 524 match classify_name_ref(sema, &name_ref) {
525 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), 525 Some(name_kind) => match name_kind {
526 NameRefClass::Definition(def) => { 526 NameRefClass::ExternCrate(_) => HighlightTag::Module.into(),
527 if let Definition::Local(local) = &def { 527 NameRefClass::Definition(def) => {
528 if let Some(name) = local.name(db) { 528 if let Definition::Local(local) = &def {
529 let shadow_count = 529 if let Some(name) = local.name(db) {
530 bindings_shadow_count.entry(name.clone()).or_default(); 530 let shadow_count =
531 binding_hash = Some(calc_binding_hash(&name, *shadow_count)) 531 bindings_shadow_count.entry(name.clone()).or_default();
532 } 532 binding_hash = Some(calc_binding_hash(&name, *shadow_count))
533 }; 533 }
534 highlight_name(sema, db, def, Some(name_ref), possibly_unsafe) 534 };
535 highlight_name(sema, db, def, Some(name_ref), possibly_unsafe)
536 }
537 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
538 },
539 None if syntactic_name_ref_highlighting => {
540 highlight_name_ref_by_syntax(name_ref, sema)
535 } 541 }
536 NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), 542 None => HighlightTag::UnresolvedReference.into(),
537 },
538 None if syntactic_name_ref_highlighting => {
539 highlight_name_ref_by_syntax(name_ref, sema)
540 } 543 }
541 None => HighlightTag::UnresolvedReference.into(), 544 })
542 }
543 } 545 }
544 546
545 // Simple token-based highlighting 547 // Simple token-based highlighting
@@ -700,6 +702,35 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
700 } 702 }
701} 703}
702 704
705fn highlight_func_by_name_ref(
706 sema: &Semantics<RootDatabase>,
707 name_ref: &ast::NameRef,
708) -> Option<Highlight> {
709 let parent = name_ref.syntax().parent()?;
710 let method_call = ast::MethodCallExpr::cast(parent)?;
711 highlight_method_call(sema, &method_call)
712}
713
714fn highlight_method_call(
715 sema: &Semantics<RootDatabase>,
716 method_call: &ast::MethodCallExpr,
717) -> Option<Highlight> {
718 let func = sema.resolve_method_call(&method_call)?;
719 let mut h = HighlightTag::Function.into();
720 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
721 h |= HighlightModifier::Unsafe;
722 }
723
724 sema.method_reciever_kind(&method_call)
725 .map(|self_kind| match self_kind {
726 SelfKind::Shared => h,
727 SelfKind::Mutable => h | HighlightModifier::Mutable,
728 SelfKind::Consuming => h | HighlightModifier::Consuming,
729 SelfKind::Copied => h,
730 })
731 .or_else(|| Some(h))
732}
733
703fn highlight_name( 734fn highlight_name(
704 sema: &Semantics<RootDatabase>, 735 sema: &Semantics<RootDatabase>,
705 db: &RootDatabase, 736 db: &RootDatabase,
@@ -722,20 +753,26 @@ fn highlight_name(
722 Definition::ModuleDef(def) => match def { 753 Definition::ModuleDef(def) => match def {
723 hir::ModuleDef::Module(_) => HighlightTag::Module, 754 hir::ModuleDef::Module(_) => HighlightTag::Module,
724 hir::ModuleDef::Function(func) => { 755 hir::ModuleDef::Function(func) => {
725 let mut h = HighlightTag::Function.into(); 756 return name_ref
726 if func.is_unsafe(db) { 757 .and_then(|name_ref| highlight_func_by_name_ref(sema, &name_ref))
727 h |= HighlightModifier::Unsafe; 758 .unwrap_or_else(|| {
728 } else { 759 let mut h = HighlightTag::Function.into();
729 let is_unsafe = name_ref 760 if func.is_unsafe(db) {
730 .and_then(|name_ref| name_ref.syntax().parent()) 761 h |= HighlightModifier::Unsafe;
731 .and_then(ast::MethodCallExpr::cast) 762 }
732 .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) 763
733 .unwrap_or(false); 764 return if func.has_self_param(db) {
734 if is_unsafe { 765 match func.mutability_of_self_param(db) {
735 h |= HighlightModifier::Unsafe; 766 Some(mutability) => match mutability {
736 } 767 Mutability::Mut => h | HighlightModifier::Mutable,
737 } 768 Mutability::Shared => h,
738 return h; 769 },
770 None => h,
771 }
772 } else {
773 h
774 };
775 });
739 } 776 }
740 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, 777 hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
741 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum, 778 hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
@@ -807,15 +844,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
807 844
808 match parent.kind() { 845 match parent.kind() {
809 METHOD_CALL_EXPR => { 846 METHOD_CALL_EXPR => {
810 let mut h = Highlight::new(HighlightTag::Function); 847 return ast::MethodCallExpr::cast(parent)
811 let is_unsafe = ast::MethodCallExpr::cast(parent) 848 .and_then(|method_call| highlight_method_call(sema, &method_call))
812 .map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) 849 .unwrap_or_else(|| HighlightTag::Function.into());
813 .unwrap_or(false);
814 if is_unsafe {
815 h |= HighlightModifier::Unsafe;
816 }
817
818 h
819 } 850 }
820 FIELD_EXPR => { 851 FIELD_EXPR => {
821 let h = HighlightTag::Field; 852 let h = HighlightTag::Field;
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 49ec94bdc..c1b817f06 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -62,6 +62,7 @@ pub enum HighlightModifier {
62 Documentation, 62 Documentation,
63 Injected, 63 Injected,
64 Mutable, 64 Mutable,
65 Consuming,
65 Unsafe, 66 Unsafe,
66} 67}
67 68
@@ -119,6 +120,7 @@ impl HighlightModifier {
119 HighlightModifier::Documentation, 120 HighlightModifier::Documentation,
120 HighlightModifier::Injected, 121 HighlightModifier::Injected,
121 HighlightModifier::Mutable, 122 HighlightModifier::Mutable,
123 HighlightModifier::Consuming,
122 HighlightModifier::Unsafe, 124 HighlightModifier::Unsafe,
123 ]; 125 ];
124 126
@@ -130,6 +132,7 @@ impl HighlightModifier {
130 HighlightModifier::Documentation => "documentation", 132 HighlightModifier::Documentation => "documentation",
131 HighlightModifier::Injected => "injected", 133 HighlightModifier::Injected => "injected",
132 HighlightModifier::Mutable => "mutable", 134 HighlightModifier::Mutable => "mutable",
135 HighlightModifier::Consuming => "consuming",
133 HighlightModifier::Unsafe => "unsafe", 136 HighlightModifier::Unsafe => "unsafe",
134 } 137 }
135 } 138 }
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 94f37d773..ccb76f552 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -12,6 +12,12 @@ fn test_highlighting() {
12use inner::{self as inner_mod}; 12use inner::{self as inner_mod};
13mod inner {} 13mod inner {}
14 14
15// Needed for function consuming vs normal
16pub mod marker {
17 #[lang = "copy"]
18 pub trait Copy {}
19}
20
15#[derive(Clone, Debug)] 21#[derive(Clone, Debug)]
16struct Foo { 22struct Foo {
17 pub x: i32, 23 pub x: i32,
@@ -36,6 +42,29 @@ impl Foo {
36 fn qux(&mut self) { 42 fn qux(&mut self) {
37 self.x = 0; 43 self.x = 0;
38 } 44 }
45
46 fn quop(&self) -> i32 {
47 self.x
48 }
49}
50
51#[derive(Copy, Clone)]
52struct FooCopy {
53 x: u32,
54}
55
56impl FooCopy {
57 fn baz(self) -> u32 {
58 self.x
59 }
60
61 fn qux(&mut self) {
62 self.x = 0;
63 }
64
65 fn quop(&self) -> u32 {
66 self.x
67 }
39} 68}
40 69
41static mut STATIC_MUT: i32 = 0; 70static mut STATIC_MUT: i32 = 0;
@@ -87,6 +116,16 @@ fn main() {
87 let Foo { x: z, y } = Foo { x: z, y }; 116 let Foo { x: z, y } = Foo { x: z, y };
88 117
89 y; 118 y;
119
120 let mut foo = Foo { x, y: x };
121 foo.quop();
122 foo.qux();
123 foo.baz();
124
125 let mut copy = FooCopy { x };
126 copy.quop();
127 copy.qux();
128 copy.baz();
90} 129}
91 130
92enum Option<T> { 131enum Option<T> {
diff --git a/crates/ide/test_data/highlighting.html b/crates/ide/test_data/highlighting.html
index 8e0160eee..a6b79589b 100644
--- a/crates/ide/test_data/highlighting.html
+++ b/crates/ide/test_data/highlighting.html
@@ -38,6 +38,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
38<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> 38<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span>
39<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> 39<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span>
40 40
41<span class="comment">// Needed for function consuming vs normal</span>
42<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span>
43 <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"copy"</span><span class="attribute">]</span>
44 <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span>
45<span class="punctuation">}</span>
46
41<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span> 47<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span>
42<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> 48<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
43 <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> 49 <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span>
@@ -59,9 +65,32 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
59 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span> 65 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
60 <span class="punctuation">}</span> 66 <span class="punctuation">}</span>
61 67
62 <span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> 68 <span class="keyword">fn</span> <span class="function declaration mutable">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
63 <span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> 69 <span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
64 <span class="punctuation">}</span> 70 <span class="punctuation">}</span>
71
72 <span class="keyword">fn</span> <span class="function declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
73 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
74 <span class="punctuation">}</span>
75<span class="punctuation">}</span>
76
77<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Copy</span><span class="punctuation">,</span><span class="attribute"> Clone</span><span class="punctuation">)</span><span class="attribute">]</span>
78<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="punctuation">{</span>
79 <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span>
80<span class="punctuation">}</span>
81
82<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span>
83 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
84 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
85 <span class="punctuation">}</span>
86
87 <span class="keyword">fn</span> <span class="function declaration mutable">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
88 <span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
89 <span class="punctuation">}</span>
90
91 <span class="keyword">fn</span> <span class="function declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
92 <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
93 <span class="punctuation">}</span>
65<span class="punctuation">}</span> 94<span class="punctuation">}</span>
66 95
67<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> 96<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
@@ -113,6 +142,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
113 <span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span> 142 <span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span>
114 143
115 <span class="variable">y</span><span class="punctuation">;</span> 144 <span class="variable">y</span><span class="punctuation">;</span>
145
146 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
147 <span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
148 <span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
149 <span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
150
151 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
152 <span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
153 <span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
154 <span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function">baz</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
116<span class="punctuation">}</span> 155<span class="punctuation">}</span>
117 156
118<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 157<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index afc38fb4e..9db7b8af5 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -75,6 +75,7 @@ define_semantic_token_modifiers![
75 (CONTROL_FLOW, "controlFlow"), 75 (CONTROL_FLOW, "controlFlow"),
76 (INJECTED, "injected"), 76 (INJECTED, "injected"),
77 (MUTABLE, "mutable"), 77 (MUTABLE, "mutable"),
78 (CONSUMING, "consuming"),
78 (UNSAFE, "unsafe"), 79 (UNSAFE, "unsafe"),
79 (ATTRIBUTE_MODIFIER, "attribute"), 80 (ATTRIBUTE_MODIFIER, "attribute"),
80]; 81];
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 643dcb4fc..a5191c16e 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -400,6 +400,7 @@ fn semantic_token_type_and_modifiers(
400 HighlightModifier::Injected => semantic_tokens::INJECTED, 400 HighlightModifier::Injected => semantic_tokens::INJECTED,
401 HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW, 401 HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW,
402 HighlightModifier::Mutable => semantic_tokens::MUTABLE, 402 HighlightModifier::Mutable => semantic_tokens::MUTABLE,
403 HighlightModifier::Consuming => semantic_tokens::CONSUMING,
403 HighlightModifier::Unsafe => semantic_tokens::UNSAFE, 404 HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
404 }; 405 };
405 mods |= modifier; 406 mods |= modifier;