Skip to content

Commit eb7136f

Browse files
Merge #5957
5957: Add consuming modifier to lvalues that are passed by value and not Copy r=jonas-schievink a=Nashenas88 Related to #5856 Co-authored-by: Paul Daniel Faria <[email protected]>
2 parents 868f4b5 + a1a7b07 commit eb7136f

File tree

3 files changed

+66
-23
lines changed

3 files changed

+66
-23
lines changed

crates/ide/src/syntax_highlighting.rs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod injection;
44
#[cfg(test)]
55
mod tests;
66

7-
use hir::{Name, Semantics, VariantDef};
7+
use hir::{Local, Name, Semantics, VariantDef};
88
use ide_db::{
99
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
1010
RootDatabase,
@@ -13,8 +13,8 @@ use rustc_hash::FxHashMap;
1313
use syntax::{
1414
ast::{self, HasFormatSpecifier},
1515
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement,
16-
SyntaxKind::*,
17-
TextRange, WalkEvent, T,
16+
SyntaxKind::{self, *},
17+
SyntaxNode, SyntaxToken, TextRange, WalkEvent, T,
1818
};
1919

2020
use crate::FileId;
@@ -454,6 +454,32 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
454454
Some(TextRange::new(range_start, range_end))
455455
}
456456

457+
/// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly.
458+
fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[SyntaxKind]) -> bool {
459+
while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) {
460+
if parent.kind() != *kind {
461+
return false;
462+
}
463+
464+
// FIXME: Would be nice to get parent out of the match, but binding by-move and by-value
465+
// in the same pattern is unstable: rust-lang/rust#68354.
466+
node = node.parent().unwrap().into();
467+
kinds = rest;
468+
}
469+
470+
// Only true if we matched all expected kinds
471+
kinds.len() == 0
472+
}
473+
474+
fn is_consumed_lvalue(
475+
node: NodeOrToken<SyntaxNode, SyntaxToken>,
476+
local: &Local,
477+
db: &RootDatabase,
478+
) -> bool {
479+
// When lvalues are passed as arguments and they're not Copy, then mark them as Consuming.
480+
parents_match(node, &[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST]) && !local.ty(db).is_copy(db)
481+
}
482+
457483
fn highlight_element(
458484
sema: &Semantics<RootDatabase>,
459485
bindings_shadow_count: &mut FxHashMap<Name, u32>,
@@ -522,6 +548,12 @@ fn highlight_element(
522548

523549
let mut h = highlight_def(db, def);
524550

551+
if let Definition::Local(local) = &def {
552+
if is_consumed_lvalue(name_ref.syntax().clone().into(), local, db) {
553+
h |= HighlightModifier::Consuming;
554+
}
555+
}
556+
525557
if let Some(parent) = name_ref.syntax().parent() {
526558
if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) {
527559
if let Definition::Field(field) = def {
@@ -645,21 +677,30 @@ fn highlight_element(
645677
.and_then(ast::SelfParam::cast)
646678
.and_then(|p| p.mut_token())
647679
.is_some();
648-
// closure to enforce lazyness
649-
let self_path = || {
650-
sema.resolve_path(&element.parent()?.parent().and_then(ast::Path::cast)?)
651-
};
680+
let self_path = &element
681+
.parent()
682+
.as_ref()
683+
.and_then(SyntaxNode::parent)
684+
.and_then(ast::Path::cast)
685+
.and_then(|p| sema.resolve_path(&p));
686+
let mut h = HighlightTag::SelfKeyword.into();
652687
if self_param_is_mut
653-
|| matches!(self_path(),
688+
|| matches!(self_path,
654689
Some(hir::PathResolution::Local(local))
655690
if local.is_self(db)
656691
&& (local.is_mut(db) || local.ty(db).is_mutable_reference())
657692
)
658693
{
659-
HighlightTag::SelfKeyword | HighlightModifier::Mutable
660-
} else {
661-
HighlightTag::SelfKeyword.into()
694+
h |= HighlightModifier::Mutable
662695
}
696+
697+
if let Some(hir::PathResolution::Local(local)) = self_path {
698+
if is_consumed_lvalue(element, &local, db) {
699+
h |= HighlightModifier::Consuming;
700+
}
701+
}
702+
703+
h
663704
}
664705
T![ref] => element
665706
.parent()

crates/ide/src/syntax_highlighting/test_data/highlighting.html

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
<span class="punctuation">}</span>
6262

6363
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
64-
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
65-
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
64+
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
65+
<span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword consuming">self</span><span class="punctuation">)</span>
6666
<span class="punctuation">}</span>
6767

6868
<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>
@@ -80,8 +80,8 @@
8080
<span class="punctuation">}</span>
8181

8282
<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>
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="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
84+
<span class="value_param">f</span><span class="punctuation">.</span><span class="function">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
8585
<span class="punctuation">}</span>
8686

8787
<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>
@@ -144,14 +144,15 @@
144144
<span class="variable">y</span><span class="punctuation">;</span>
145145

146146
<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="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="variable mutable">foo</span><span class="punctuation">.</span><span class="unresolved_reference">clone</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
147148
<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>
148149
<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+
<span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span>
150151

151152
<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>
152153
<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>
153154
<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>
155+
<span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span>
155156
<span class="punctuation">}</span>
156157

157158
<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>

crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl Bar for Foo {
3535
}
3636
3737
impl Foo {
38-
fn baz(mut self) -> i32 {
39-
self.x
38+
fn baz(mut self, f: Foo) -> i32 {
39+
f.baz(self)
4040
}
4141
4242
fn qux(&mut self) {
@@ -54,8 +54,8 @@ struct FooCopy {
5454
}
5555
5656
impl FooCopy {
57-
fn baz(self) -> u32 {
58-
self.x
57+
fn baz(self, f: FooCopy) -> u32 {
58+
f.baz(self)
5959
}
6060
6161
fn qux(&mut self) {
@@ -118,14 +118,15 @@ fn main() {
118118
y;
119119
120120
let mut foo = Foo { x, y: x };
121+
let foo2 = foo.clone();
121122
foo.quop();
122123
foo.qux();
123-
foo.baz();
124+
foo.baz(foo2);
124125
125126
let mut copy = FooCopy { x };
126127
copy.quop();
127128
copy.qux();
128-
copy.baz();
129+
copy.baz(copy);
129130
}
130131
131132
enum Option<T> {

0 commit comments

Comments
 (0)