summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-completion
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /src/tools/rust-analyzer/crates/ide-completion
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-completion')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs62
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs59
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs60
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs1
15 files changed, 246 insertions, 38 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index eb87d6c58..c3136f6df 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -23,7 +23,7 @@ pub(crate) mod env_vars;
use std::iter;
-use hir::{known, ScopeDef};
+use hir::{known, ScopeDef, Variant};
use ide_db::{imports::import_assets::LocatedImport, SymbolKind};
use syntax::ast;
@@ -537,17 +537,20 @@ fn enum_variants_with_paths(
impl_: &Option<ast::Impl>,
cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath),
) {
+ let mut process_variant = |variant: Variant| {
+ let self_path = hir::ModPath::from_segments(
+ hir::PathKind::Plain,
+ iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
+ );
+
+ cb(acc, ctx, variant, self_path);
+ };
+
let variants = enum_.variants(ctx.db);
if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
- for &variant in &variants {
- let self_path = hir::ModPath::from_segments(
- hir::PathKind::Plain,
- iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
- );
- cb(acc, ctx, variant, self_path);
- }
+ variants.iter().for_each(|variant| process_variant(*variant));
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index 7c6e5e100..77246379e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -122,7 +122,7 @@ fn complete_methods(
mut f: impl FnMut(hir::Function),
) {
let mut seen_methods = FxHashSet::default();
- receiver.iterate_method_candidates(
+ receiver.iterate_method_candidates_with_traits(
ctx.db,
&ctx.scope,
&ctx.traits_in_scope(),
@@ -415,7 +415,6 @@ fn foo(a: lib::A) { a.$0 }
fn test_local_impls() {
check(
r#"
-//- /lib.rs crate:lib
pub struct A {}
mod m {
impl super::A {
@@ -427,9 +426,8 @@ mod m {
}
}
}
-//- /main.rs crate:main deps:lib
-fn foo(a: lib::A) {
- impl lib::A {
+fn foo(a: A) {
+ impl A {
fn local_method(&self) {}
}
a.$0
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index 364969af9..0979f6a6d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -5,10 +5,7 @@ use ide_db::imports::{
insert_use::ImportScope,
};
use itertools::Itertools;
-use syntax::{
- ast::{self},
- AstNode, SyntaxNode, T,
-};
+use syntax::{ast, AstNode, SyntaxNode, T};
use crate::{
context::{
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
index 37849c251..69c05a76d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
@@ -33,7 +33,9 @@ pub(crate) fn complete_type_path(
// Don't suggest attribute macros and derives.
ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
// Type things are fine
- ScopeDef::ModuleDef(BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_))
+ ScopeDef::ModuleDef(
+ BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TraitAlias(_) | TypeAlias(_),
+ )
| ScopeDef::AdtSelfType(_)
| ScopeDef::Unknown
| ScopeDef::GenericParam(TypeParam(_)) => true,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index ea54068b0..8cbf89e9c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -6,13 +6,13 @@ mod tests;
use std::iter;
-use base_db::SourceDatabaseExt;
use hir::{
HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
};
use ide_db::{
base_db::{FilePosition, SourceDatabase},
famous_defs::FamousDefs,
+ helpers::is_editable_crate,
FxHashMap, FxHashSet, RootDatabase,
};
use syntax::{
@@ -220,6 +220,8 @@ pub(super) struct PatternContext {
/// The record pattern this name or ref is a field of
pub(super) record_pat: Option<ast::RecordPat>,
pub(super) impl_: Option<ast::Impl>,
+ /// List of missing variants in a match expr
+ pub(super) missing_variants: Vec<hir::Variant>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -387,8 +389,7 @@ pub(crate) struct CompletionContext<'a> {
impl<'a> CompletionContext<'a> {
/// The range of the identifier that is being completed.
pub(crate) fn source_range(&self) -> TextRange {
- // check kind of macro-expanded token, but use range of original token
- let kind = self.token.kind();
+ let kind = self.original_token.kind();
match kind {
CHAR => {
// assume we are completing a lifetime but the user has only typed the '
@@ -416,6 +417,7 @@ impl<'a> CompletionContext<'a> {
hir::ModuleDef::Const(it) => self.is_visible(it),
hir::ModuleDef::Static(it) => self.is_visible(it),
hir::ModuleDef::Trait(it) => self.is_visible(it),
+ hir::ModuleDef::TraitAlias(it) => self.is_visible(it),
hir::ModuleDef::TypeAlias(it) => self.is_visible(it),
hir::ModuleDef::Macro(it) => self.is_visible(it),
hir::ModuleDef::BuiltinType(_) => Visible::Yes,
@@ -525,10 +527,11 @@ impl<'a> CompletionContext<'a> {
return Visible::No;
}
// If the definition location is editable, also show private items
- let root_file = defining_crate.root_file(self.db);
- let source_root_id = self.db.file_source_root(root_file);
- let is_editable = !self.db.source_root(source_root_id).is_library;
- return if is_editable { Visible::Editable } else { Visible::No };
+ return if is_editable_crate(defining_crate, self.db) {
+ Visible::Editable
+ } else {
+ Visible::No
+ };
}
if self.is_doc_hidden(attrs, defining_crate) {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index db0045aef..a94c40458 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -1,7 +1,7 @@
//! Module responsible for analyzing the code surrounding the cursor for completion.
use std::iter;
-use hir::{Semantics, Type, TypeInfo};
+use hir::{Semantics, Type, TypeInfo, Variant};
use ide_db::{active_parameter::ActiveParameter, RootDatabase};
use syntax::{
algo::{find_node_at_offset, non_trivia_sibling},
@@ -353,7 +353,7 @@ fn expected_type_and_name(
_ => ty,
};
- loop {
+ let (ty, name) = loop {
break match_ast! {
match node {
ast::LetStmt(it) => {
@@ -385,9 +385,7 @@ fn expected_type_and_name(
token.clone(),
).map(|ap| {
let name = ap.ident().map(NameOrNameRef::Name);
-
- let ty = strip_refs(ap.ty);
- (Some(ty), name)
+ (Some(ap.ty), name)
})
.unwrap_or((None, None))
},
@@ -489,7 +487,8 @@ fn expected_type_and_name(
},
}
};
- }
+ };
+ (ty.map(strip_refs), name)
}
fn classify_lifetime(
@@ -1133,6 +1132,9 @@ fn pattern_context_for(
pat: ast::Pat,
) -> PatternContext {
let mut param_ctx = None;
+
+ let mut missing_variants = vec![];
+
let (refutability, has_type_ascription) =
pat
.syntax()
@@ -1162,7 +1164,52 @@ fn pattern_context_for(
})();
return (PatternRefutability::Irrefutable, has_type_ascription)
},
- ast::MatchArm(_) => PatternRefutability::Refutable,
+ ast::MatchArm(match_arm) => {
+ let missing_variants_opt = match_arm
+ .syntax()
+ .parent()
+ .and_then(ast::MatchArmList::cast)
+ .and_then(|match_arm_list| {
+ match_arm_list
+ .syntax()
+ .parent()
+ .and_then(ast::MatchExpr::cast)
+ .and_then(|match_expr| {
+ let expr_opt = find_opt_node_in_file(&original_file, match_expr.expr());
+
+ expr_opt.and_then(|expr| {
+ sema.type_of_expr(&expr)?
+ .adjusted()
+ .autoderef(sema.db)
+ .find_map(|ty| match ty.as_adt() {
+ Some(hir::Adt::Enum(e)) => Some(e),
+ _ => None,
+ }).and_then(|enum_| {
+ Some(enum_.variants(sema.db))
+ })
+ })
+ }).and_then(|variants| {
+ Some(variants.iter().filter_map(|variant| {
+ let variant_name = variant.name(sema.db).to_string();
+
+ let variant_already_present = match_arm_list.arms().any(|arm| {
+ arm.pat().and_then(|pat| {
+ let pat_already_present = pat.syntax().to_string().contains(&variant_name);
+ pat_already_present.then(|| pat_already_present)
+ }).is_some()
+ });
+
+ (!variant_already_present).then_some(variant.clone())
+ }).collect::<Vec<Variant>>())
+ })
+ });
+
+ if let Some(missing_variants_) = missing_variants_opt {
+ missing_variants = missing_variants_;
+ };
+
+ PatternRefutability::Refutable
+ },
ast::LetExpr(_) => PatternRefutability::Refutable,
ast::ForExpr(_) => PatternRefutability::Irrefutable,
_ => PatternRefutability::Irrefutable,
@@ -1184,6 +1231,7 @@ fn pattern_context_for(
ref_token,
record_pat: None,
impl_: fetch_immediate_impl(sema, original_file, pat.syntax()),
+ missing_variants,
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
index a654a5db5..82a1c10c5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
@@ -411,3 +411,15 @@ fn main() {
expect!["ty: i32, name: ?"],
);
}
+
+#[test]
+fn expected_type_ref_return_pos() {
+ check_expected_type_and_name(
+ r#"
+fn f(thing: u32) -> &u32 {
+ &thin$0
+}
+"#,
+ expect!["ty: u32, name: ?"],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index 2f65491d8..bb9fa7cca 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -288,7 +288,7 @@ impl_from!(SymbolKind for CompletionItemKind);
impl CompletionItemKind {
#[cfg(test)]
- pub(crate) fn tag(&self) -> &'static str {
+ pub(crate) fn tag(self) -> &'static str {
match self {
CompletionItemKind::SymbolKind(kind) => match kind {
SymbolKind::Attribute => "at",
@@ -312,6 +312,7 @@ impl CompletionItemKind {
SymbolKind::Struct => "st",
SymbolKind::ToolModule => "tm",
SymbolKind::Trait => "tt",
+ SymbolKind::TraitAlias => "tr",
SymbolKind::TypeAlias => "ta",
SymbolKind::TypeParam => "tp",
SymbolKind::Union => "un",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index d99ad5f9f..c1f51aabb 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -367,6 +367,9 @@ fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
+ ScopeDef::ModuleDef(TraitAlias(..)) => {
+ CompletionItemKind::SymbolKind(SymbolKind::TraitAlias)
+ }
ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
index ffcad1185..44e886076 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
@@ -267,4 +267,63 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn complete_missing_macro_arg() {
+ // Regression test for https://github.com/rust-lang/rust-analyzer/issues/14246
+ check_edit(
+ "BAR",
+ r#"
+macro_rules! foo {
+ ($val:ident, $val2: ident) => {
+ $val $val2
+ };
+}
+
+const BAR: u32 = 9;
+fn main() {
+ foo!(BAR, $0)
+}
+"#,
+ r#"
+macro_rules! foo {
+ ($val:ident, $val2: ident) => {
+ $val $val2
+ };
+}
+
+const BAR: u32 = 9;
+fn main() {
+ foo!(BAR, BAR)
+}
+"#,
+ );
+ check_edit(
+ "BAR",
+ r#"
+macro_rules! foo {
+ ($val:ident, $val2: ident) => {
+ $val $val2
+ };
+}
+
+const BAR: u32 = 9;
+fn main() {
+ foo!($0)
+}
+"#,
+ r#"
+macro_rules! foo {
+ ($val:ident, $val2: ident) => {
+ $val $val2
+ };
+}
+
+const BAR: u32 = 9;
+fn main() {
+ foo!(BAR)
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
index 21b4bc217..9225c91be 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
@@ -37,7 +37,9 @@ pub(crate) fn render_struct_pat(
let lookup = format_literal_lookup(name.as_str(), kind);
let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
- Some(build_completion(ctx, label, lookup, pat, strukt))
+ let db = ctx.db();
+
+ Some(build_completion(ctx, label, lookup, pat, strukt, strukt.ty(db), false))
}
pub(crate) fn render_variant_pat(
@@ -52,6 +54,7 @@ pub(crate) fn render_variant_pat(
let fields = variant.fields(ctx.db());
let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, variant)?;
+ let enum_ty = variant.parent_enum(ctx.db()).ty(ctx.db());
let (name, escaped_name) = match path {
Some(path) => (path.unescaped().to_string().into(), path.to_string().into()),
@@ -81,7 +84,15 @@ pub(crate) fn render_variant_pat(
}
};
- Some(build_completion(ctx, label, lookup, pat, variant))
+ Some(build_completion(
+ ctx,
+ label,
+ lookup,
+ pat,
+ variant,
+ enum_ty,
+ pattern_ctx.missing_variants.contains(&variant),
+ ))
}
fn build_completion(
@@ -90,13 +101,22 @@ fn build_completion(
lookup: SmolStr,
pat: String,
def: impl HasAttrs + Copy,
+ adt_ty: hir::Type,
+ // Missing in context of match statement completions
+ is_variant_missing: bool,
) -> CompletionItem {
+ let mut relevance = ctx.completion_relevance();
+
+ if is_variant_missing {
+ relevance.type_match = super::compute_type_match(ctx.completion, &adt_ty);
+ }
+
let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
item.set_documentation(ctx.docs(def))
.set_deprecated(ctx.is_deprecated(def))
.detail(&pat)
.lookup_by(lookup)
- .set_relevance(ctx.completion_relevance());
+ .set_relevance(relevance);
match ctx.snippet_cap() {
Some(snippet_cap) => item.insert_snippet(snippet_cap, pat),
None => item.insert_text(pat),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
index 4e60820dd..c97144b61 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
@@ -857,9 +857,9 @@ mod lint {
#[test]
fn lint_feature() {
check_edit(
- "box_syntax",
+ "box_patterns",
r#"#[feature(box_$0)] struct Test;"#,
- r#"#[feature(box_syntax)] struct Test;"#,
+ r#"#[feature(box_patterns)] struct Test;"#,
)
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
index ad9254e7f..c0e485c36 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
@@ -614,6 +614,7 @@ fn f(u: U) {
check_empty(
r#"
+#![rustc_coherence_is_core]
#[lang = "u32"]
impl u32 {
pub const MIN: Self = 0;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
index 328faaa06..65cefdb08 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
@@ -47,6 +47,66 @@ fn foo(s: Struct) {
}
#[test]
+fn record_pattern_field_enum() {
+ check(
+ r#"
+//- minicore:result
+enum Baz { Foo, Bar }
+
+fn foo(baz: Baz) {
+ match baz {
+ Baz::Foo => (),
+ $0
+ }
+}
+"#,
+ expect![[r#"
+ en Baz
+ en Result
+ md core
+ ev Err
+ ev Ok
+ bn Baz::Bar Baz::Bar$0
+ bn Baz::Foo Baz::Foo$0
+ bn Err(…) Err($1)$0
+ bn Ok(…) Ok($1)$0
+ kw mut
+ kw ref
+ "#]],
+ );
+
+ check(
+ r#"
+//- minicore:result
+enum Baz { Foo, Bar }
+
+fn foo(baz: Baz) {
+ use Baz::*;
+ match baz {
+ Foo => (),
+ $0
+ }
+}
+ "#,
+ expect![[r#"
+ en Baz
+ en Result
+ md core
+ ev Bar
+ ev Err
+ ev Foo
+ ev Ok
+ bn Bar Bar$0
+ bn Err(…) Err($1)$0
+ bn Foo Foo$0
+ bn Ok(…) Ok($1)$0
+ kw mut
+ kw ref
+ "#]],
+ );
+}
+
+#[test]
fn pattern_enum_variant() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
index cb71c7b2b..f8a6f6cd3 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
@@ -608,6 +608,7 @@ fn f() {
}
//- /core.rs crate:core
+#![rustc_coherence_is_core]
#[lang = "u8"]
impl u8 {
pub const MAX: Self = 255;