Skip to content
Open
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
29 changes: 15 additions & 14 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2790,25 +2790,26 @@ impl Function {
}

let ret_type = self.ret_type(db);
let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
let lang_items = hir_def::lang_item::lang_items(db, self.krate(db).id);
let Some(future_trait_id) = lang_items.Future else {
return false;
};
let Some(sized_trait_id) = lang_items.Sized else {
return false;
};

let mut has_impl_future = false;
impl_traits
.filter(|t| {
let fut = t.id == future_trait_id;
has_impl_future |= fut;
!fut && t.id != sized_trait_id
})
// all traits but the future trait must be auto traits
.all(|t| t.is_auto(db))
&& has_impl_future
if let Some(impl_traits) = ret_type.as_impl_traits(db) {
let sized_trait_id = lang_items.Sized;
let mut has_impl_future = false;
return impl_traits
.filter(|t| {
let fut = t.id == future_trait_id;
has_impl_future |= fut;
!fut && sized_trait_id.map_or(true, |sid| t.id != sid)
})
// all traits but the future trait must be auto traits
.all(|t| t.is_auto(db))
&& has_impl_future;
}

ret_type.impls_trait(db, Trait::from(future_trait_id), &[])
}

/// Does this function have `#[test]` attribute?
Expand Down
4 changes: 2 additions & 2 deletions crates/ide/src/syntax_highlighting/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ pub(super) fn highlight_def(
if !is_ref && func.is_unsafe_to_call(db, None, edition) {
h |= HlMod::Unsafe;
}
if func.is_async(db) {
if func.returns_impl_future(db) {
h |= HlMod::Async;
}
if func.is_const(db) {
Expand Down Expand Up @@ -706,7 +706,7 @@ fn highlight_method_call(
if is_unsafe {
h |= HlMod::Unsafe;
}
if func.is_async(sema.db) {
if func.returns_impl_future(sema.db) {
h |= HlMod::Async;
}
if func.is_const(sema.db) {
Expand Down
96 changes: 96 additions & 0 deletions crates/ide/src/syntax_highlighting/test_data/highlight_async.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

<style>
body { margin: 0; }
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }

.lifetime { color: #DFAF8F; font-style: italic; }
.label { color: #DFAF8F; font-style: italic; }
.comment { color: #7F9F7F; }
.documentation { color: #629755; }
.intra_doc_link { font-style: italic; }
.injected { opacity: 0.65 ; }
.struct, .enum { color: #7CB8BB; }
.enum_variant { color: #BDE0F3; }
.string_literal { color: #CC9393; }
.field { color: #94BFF3; }
.function { color: #93E0E3; }
.parameter { color: #94BFF3; }
.text { color: #DCDCCC; }
.type { color: #7CB8BB; }
.builtin_type { color: #8CD0D3; }
.type_param { color: #DFAF8F; }
.attribute { color: #94BFF3; }
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.proc_macro { color: #94BFF3; text-decoration: underline; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }
.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.escape_sequence { color: #94BFF3; }
.keyword { color: #F0DFAF; font-weight: bold; }
.control { font-style: italic; }
.reference { font-style: italic; font-weight: bold; }
.const { font-weight: bolder; }
.unsafe { color: #BC8383; }
.deprecated { text-decoration: line-through; }

.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="keyword">use</span> <span class="crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">future</span><span class="operator">::</span><span class="trait default_library library">Future</span><span class="semicolon">;</span>
<span class="keyword">use</span> <span class="crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">pin</span><span class="operator">::</span><span class="struct default_library library">Pin</span><span class="semicolon">;</span>
<span class="keyword">use</span> <span class="crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">task</span><span class="operator">::</span><span class="brace">{</span><span class="struct default_library library">Context</span><span class="comma">,</span> <span class="enum default_library library">Poll</span><span class="brace">}</span><span class="semicolon">;</span>

<span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function async declaration">async_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>

<span class="keyword">fn</span> <span class="function async declaration">returns_impl_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="keyword">impl</span> <span class="trait default_library library">Future</span><span class="angle">&lt;</span><span class="type_alias associated default_library library static trait">Output</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="keyword async">async</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>

<span class="keyword">struct</span> <span class="struct declaration">MyFuture</span><span class="semicolon">;</span>

<span class="keyword">impl</span> <span class="trait default_library library">Future</span> <span class="keyword">for</span> <span class="struct">MyFuture</span> <span class="brace">{</span>
<span class="keyword">type</span> <span class="type_alias associated declaration static trait">Output</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="keyword">fn</span> <span class="method associated consuming declaration trait">poll</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="colon">:</span> <span class="struct default_library library">Pin</span><span class="angle">&lt;</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_type_keyword">Self</span><span class="angle">&gt;</span><span class="comma">,</span> <span class="value_param declaration mutable reference">_cx</span><span class="colon">:</span> <span class="punctuation">&</span><span class="keyword">mut</span> <span class="struct default_library library">Context</span><span class="angle">&lt;</span><span class="lifetime">'_</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum default_library library">Poll</span><span class="angle">&lt;</span><span class="self_type_keyword">Self</span><span class="operator">::</span><span class="type_alias associated default_library library static trait">Output</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="enum default_library library">Poll</span><span class="operator">::</span><span class="enum_variant default_library library">Ready</span><span class="parenthesis">(</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
<span class="brace">}</span>
<span class="brace">}</span>

<span class="keyword">struct</span> <span class="struct declaration">Foo</span><span class="semicolon">;</span>

<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span>
<span class="keyword async">async</span> <span class="keyword">fn</span> <span class="method associated async declaration reference">async_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">fn</span> <span class="method associated async declaration reference">impl_future_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="keyword">impl</span> <span class="trait default_library library">Future</span><span class="angle">&lt;</span><span class="type_alias associated default_library library static trait">Output</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="keyword async">async</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
<span class="keyword">fn</span> <span class="method associated async declaration reference">concrete_future_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="struct">MyFuture</span> <span class="brace">{</span>
<span class="struct">MyFuture</span>
<span class="brace">}</span>
<span class="brace">}</span>

<span class="keyword">fn</span> <span class="function async declaration">returns_concrete_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="struct">MyFuture</span> <span class="brace">{</span>
<span class="struct">MyFuture</span>
<span class="brace">}</span>

<span class="keyword">type</span> <span class="type_alias declaration">AliasFuture</span> <span class="operator">=</span> <span class="struct">MyFuture</span><span class="semicolon">;</span>

<span class="keyword">fn</span> <span class="function async declaration">returns_alias_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="type_alias">AliasFuture</span> <span class="brace">{</span>
<span class="struct">MyFuture</span>
<span class="brace">}</span>

<span class="keyword">fn</span> <span class="function declaration">not_async</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>

<span class="keyword">fn</span> <span class="function declaration">use_them</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="function async">returns_impl_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="function async">returns_concrete_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="function async">returns_alias_future</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="function">not_async</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="semicolon">;</span>
<span class="variable">foo</span><span class="operator">.</span><span class="method async reference">async_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="variable">foo</span><span class="operator">.</span><span class="method async reference">impl_future_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="variable">foo</span><span class="operator">.</span><span class="method async reference">concrete_future_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span></code></pre>
64 changes: 64 additions & 0 deletions crates/ide/src/syntax_highlighting/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,3 +1584,67 @@ static STATIC: () = ();
false,
);
}

#[test]
fn test_async_highlighting() {
check_highlighting(
r#"
//- minicore: future, pin, sized
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};

async fn async_fn() {}

fn returns_impl_future() -> impl Future<Output = ()> {
async {}
}

struct MyFuture;

impl Future for MyFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(())
}
}

struct Foo;

impl Foo {
async fn async_method(&self) {}
fn impl_future_method(&self) -> impl Future<Output = ()> {
async {}
}
fn concrete_future_method(&self) -> MyFuture {
MyFuture
}
}

fn returns_concrete_future() -> MyFuture {
MyFuture
}

type AliasFuture = MyFuture;

fn returns_alias_future() -> AliasFuture {
MyFuture
}

fn not_async() {}

fn use_them() {
returns_impl_future();
returns_concrete_future();
returns_alias_future();
not_async();
let foo = Foo;
foo.async_method();
foo.impl_future_method();
foo.concrete_future_method();
}
"#,
expect_file!["./test_data/highlight_async.html"],
false,
);
}
Loading