Add consuming modifier to lvalues that are passed by value and not Copy
This commit is contained in:
parent
0275b08d15
commit
7af947a032
@ -13,8 +13,8 @@
|
||||
use syntax::{
|
||||
ast::{self, HasFormatSpecifier},
|
||||
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement,
|
||||
SyntaxKind::*,
|
||||
TextRange, WalkEvent, T,
|
||||
SyntaxKind::{self, *},
|
||||
SyntaxNode, TextRange, WalkEvent, T,
|
||||
};
|
||||
|
||||
use crate::FileId;
|
||||
@ -454,6 +454,23 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> {
|
||||
Some(TextRange::new(range_start, range_end))
|
||||
}
|
||||
|
||||
/// Returns true if the parent nodes of `node` all match the `SyntaxKind`s in `kinds` exactly.
|
||||
fn parents_match(mut node: SyntaxNode, mut kinds: &[SyntaxKind]) -> bool {
|
||||
while let (Some(parent), [kind, rest @ ..]) = (&node.parent(), kinds) {
|
||||
if parent.kind() != *kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Would be nice to get parent out of the match, but binding by-move and by-value
|
||||
// in the same pattern is unstable: rust-lang/rust#68354.
|
||||
node = node.parent().unwrap();
|
||||
kinds = rest;
|
||||
}
|
||||
|
||||
// Only true if we matched all expected kinds
|
||||
kinds.len() == 0
|
||||
}
|
||||
|
||||
fn highlight_element(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
bindings_shadow_count: &mut FxHashMap<Name, u32>,
|
||||
@ -522,6 +539,26 @@ fn highlight_element(
|
||||
|
||||
let mut h = highlight_def(db, def);
|
||||
|
||||
// When lvalues are passed as arguments and they're not Copy, then mark
|
||||
// them as Consuming.
|
||||
if parents_match(
|
||||
name_ref.syntax().clone(),
|
||||
&[PATH_SEGMENT, PATH, PATH_EXPR, ARG_LIST],
|
||||
) {
|
||||
let lvalue_ty = if let Definition::Local(local) = &def {
|
||||
Some(local.ty(db))
|
||||
} else if let Definition::SelfType(impl_def) = &def {
|
||||
Some(impl_def.target_ty(db))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(lvalue_ty) = lvalue_ty {
|
||||
if !lvalue_ty.is_copy(db) {
|
||||
h |= HighlightModifier::Consuming;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(parent) = name_ref.syntax().parent() {
|
||||
if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) {
|
||||
if let Definition::Field(field) = def {
|
||||
|
@ -61,8 +61,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
|
||||
<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">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
|
||||
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
|
||||
<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">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
|
||||
<span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<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 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span>
|
||||
<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">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
|
||||
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
|
||||
<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">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
|
||||
<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>
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<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 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
<span class="variable">y</span><span class="punctuation">;</span>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation"><</span><span class="type_param declaration">T</span><span class="punctuation">></span> <span class="punctuation">{</span>
|
||||
|
@ -35,8 +35,8 @@ fn bar(&self) -> i32 {
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn baz(mut self) -> i32 {
|
||||
self.x
|
||||
fn baz(mut self, f: Foo) -> i32 {
|
||||
f.baz(self)
|
||||
}
|
||||
|
||||
fn qux(&mut self) {
|
||||
@ -54,8 +54,8 @@ struct FooCopy {
|
||||
}
|
||||
|
||||
impl FooCopy {
|
||||
fn baz(self) -> u32 {
|
||||
self.x
|
||||
fn baz(self, f: FooCopy) -> u32 {
|
||||
f.baz(self)
|
||||
}
|
||||
|
||||
fn qux(&mut self) {
|
||||
@ -118,14 +118,15 @@ fn main() {
|
||||
y;
|
||||
|
||||
let mut foo = Foo { x, y: x };
|
||||
let foo2 = foo.clone();
|
||||
foo.quop();
|
||||
foo.qux();
|
||||
foo.baz();
|
||||
foo.baz(foo2);
|
||||
|
||||
let mut copy = FooCopy { x };
|
||||
copy.quop();
|
||||
copy.qux();
|
||||
copy.baz();
|
||||
copy.baz(copy);
|
||||
}
|
||||
|
||||
enum Option<T> {
|
||||
|
Loading…
Reference in New Issue
Block a user