Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions crates/hir/src/code_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ use hir_ty::{
autoderef,
display::{HirDisplayError, HirFormatter},
method_resolution,
traits::Solution,
traits::SolutionVariables,
traits::{FnTrait, Solution, SolutionVariables},
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty,
TyDefId, TyKind, TypeCtor,
Expand Down Expand Up @@ -1385,6 +1384,28 @@ impl Type {
)
}

/// Checks that particular type `ty` implements `std::ops::FnOnce`.
///
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
let krate = self.krate;

let fnonce_trait = match FnTrait::FnOnce.get_id(db, krate) {
Some(it) => it,
None => return false,
};

let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
method_resolution::implements_trait(
&canonical_ty,
db,
self.ty.environment.clone(),
krate,
fnonce_trait,
)
}

pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
let trait_ref = hir_ty::TraitRef {
trait_: trait_.id,
Expand Down
3 changes: 3 additions & 0 deletions crates/ide/src/syntax_highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,9 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
if local.is_mut(db) || local.ty(db).is_mutable_reference() {
h |= HighlightModifier::Mutable;
}
if local.ty(db).as_callable(db).is_some() || local.ty(db).impls_fnonce(db) {
h |= HighlightModifier::Callable;
}
return h;
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/ide/src/syntax_highlighting/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub enum HighlightModifier {
Mutable,
Consuming,
Unsafe,
Callable,
}

impl HighlightTag {
Expand Down Expand Up @@ -122,6 +123,7 @@ impl HighlightModifier {
HighlightModifier::Mutable,
HighlightModifier::Consuming,
HighlightModifier::Unsafe,
HighlightModifier::Callable,
];

fn as_str(self) -> &'static str {
Expand All @@ -134,6 +136,7 @@ impl HighlightModifier {
HighlightModifier::Mutable => "mutable",
HighlightModifier::Consuming => "consuming",
HighlightModifier::Unsafe => "unsafe",
HighlightModifier::Callable => "callable",
}
}

Expand Down
19 changes: 19 additions & 0 deletions crates/ide/src/syntax_highlighting/test_data/highlighting.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>

<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">ops</span> <span class="punctuation">{</span>
<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">"fn_once"</span><span class="attribute">]</span>
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>

<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">"fn_mut"</span><span class="attribute">]</span>
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">FnMut</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnOnce</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>

<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">"fn"</span><span class="attribute">]</span>
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Fn</span><span class="punctuation">&lt;</span><span class="type_param declaration">Args</span><span class="punctuation">&gt;</span><span class="punctuation">:</span> <span class="trait">FnMut</span><span class="punctuation">&lt;</span><span class="type_param">Args</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>


<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
<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>
Expand Down Expand Up @@ -99,6 +110,11 @@
<span class="function">foo</span><span class="operator">::</span><span class="punctuation">&lt;</span><span class="lifetime">'a</span><span class="punctuation">,</span> <span class="builtin_type">i32</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="punctuation">)</span>
<span class="punctuation">}</span>

<span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span>
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">&lt;</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span>
<span class="punctuation">}</span>

<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span>
<span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
Expand Down Expand Up @@ -157,6 +173,9 @@
<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="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span>

<span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function">baz</span><span class="punctuation">;</span>
<span class="punctuation">}</span>

<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>
Expand Down
19 changes: 19 additions & 0 deletions crates/ide/src/syntax_highlighting/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ pub mod marker {
pub trait Copy {}
}

pub mod ops {
#[lang = "fn_once"]
pub trait FnOnce<Args> {}

#[lang = "fn_mut"]
pub trait FnMut<Args>: FnOnce<Args> {}

#[lang = "fn"]
pub trait Fn<Args>: FnMut<Args> {}
}


struct Foo {
pub x: i32,
Expand Down Expand Up @@ -73,6 +84,11 @@ fn foo<'a, T>() -> T {
foo::<'a, i32>()
}

use ops::Fn;
fn baz<F: Fn() -> ()>(f: F) {
f()
}

macro_rules! def_fn {
($($tt:tt)*) => {$($tt)*}
}
Expand Down Expand Up @@ -131,6 +147,9 @@ fn main() {
copy.quop();
copy.qux();
copy.baz(copy);

let a = |x| x;
let bar = Foo::baz;
}

enum Option<T> {
Expand Down
1 change: 1 addition & 0 deletions crates/rust-analyzer/src/semantic_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ define_semantic_token_modifiers![
(CONSUMING, "consuming"),
(UNSAFE, "unsafe"),
(ATTRIBUTE_MODIFIER, "attribute"),
(CALLABLE, "callable"),
];

#[derive(Default)]
Expand Down
1 change: 1 addition & 0 deletions crates/rust-analyzer/src/to_proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ fn semantic_token_type_and_modifiers(
HighlightModifier::Mutable => semantic_tokens::MUTABLE,
HighlightModifier::Consuming => semantic_tokens::CONSUMING,
HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
HighlightModifier::Callable => semantic_tokens::CALLABLE,
};
mods |= modifier;
}
Expand Down
4 changes: 4 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@
{
"id": "consuming",
"description": "Style for non-Copy lvalues consumed by method/function call"
},
{
"id": "callable",
"description": "Style for variables/parameters that can be used in call expressions"
}
],
"semanticTokenScopes": [
Expand Down