Skip to content

Commit ee2efbc

Browse files
Allow crate authors to control completion of their things
Via the new `#[rust_analyzer::do_not_complete(...)]` attribute. Also fix a bug with existing settings for that where the paths wouldn't resolve correctly.
1 parent 78aee2a commit ee2efbc

30 files changed

+770
-289
lines changed

crates/hir-def/src/data.rs

+125-41
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup,
1313
Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId,
1414
db::DefDatabase,
15-
item_tree::{self, FnFlags, ModItem},
15+
item_tree::{self, FnFlags, ModItem, StaticFlags},
1616
nameres::proc_macro::{ProcMacroKind, parse_macro_name_and_helper_attrs},
1717
path::ImportAlias,
1818
type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap},
@@ -27,9 +27,8 @@ pub struct FunctionData {
2727
pub visibility: RawVisibility,
2828
pub abi: Option<Symbol>,
2929
pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>,
30-
pub rustc_allow_incoherent_impl: bool,
3130
pub types_map: Arc<TypesMap>,
32-
flags: FnFlags,
31+
pub flags: FnFlags,
3332
}
3433

3534
impl FunctionData {
@@ -72,7 +71,9 @@ impl FunctionData {
7271
}
7372

7473
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
75-
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
74+
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
75+
flags |= FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
76+
}
7677
if flags.contains(FnFlags::HAS_UNSAFE_KW)
7778
&& attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
7879
{
@@ -101,67 +102,103 @@ impl FunctionData {
101102
legacy_const_generics_indices: attrs.rustc_legacy_const_generics(),
102103
types_map: func.types_map.clone(),
103104
flags,
104-
rustc_allow_incoherent_impl,
105105
})
106106
}
107107

108+
#[inline]
108109
pub fn has_body(&self) -> bool {
109110
self.flags.contains(FnFlags::HAS_BODY)
110111
}
111112

112113
/// True if the first param is `self`. This is relevant to decide whether this
113114
/// can be called as a method.
115+
#[inline]
114116
pub fn has_self_param(&self) -> bool {
115117
self.flags.contains(FnFlags::HAS_SELF_PARAM)
116118
}
117119

120+
#[inline]
118121
pub fn is_default(&self) -> bool {
119122
self.flags.contains(FnFlags::HAS_DEFAULT_KW)
120123
}
121124

125+
#[inline]
122126
pub fn is_const(&self) -> bool {
123127
self.flags.contains(FnFlags::HAS_CONST_KW)
124128
}
125129

130+
#[inline]
126131
pub fn is_async(&self) -> bool {
127132
self.flags.contains(FnFlags::HAS_ASYNC_KW)
128133
}
129134

135+
#[inline]
130136
pub fn is_unsafe(&self) -> bool {
131137
self.flags.contains(FnFlags::HAS_UNSAFE_KW)
132138
}
133139

140+
#[inline]
134141
pub fn is_deprecated_safe_2024(&self) -> bool {
135142
self.flags.contains(FnFlags::DEPRECATED_SAFE_2024)
136143
}
137144

145+
#[inline]
138146
pub fn is_safe(&self) -> bool {
139147
self.flags.contains(FnFlags::HAS_SAFE_KW)
140148
}
141149

150+
#[inline]
142151
pub fn is_varargs(&self) -> bool {
143152
self.flags.contains(FnFlags::IS_VARARGS)
144153
}
145154

155+
#[inline]
146156
pub fn has_target_feature(&self) -> bool {
147157
self.flags.contains(FnFlags::HAS_TARGET_FEATURE)
148158
}
159+
160+
#[inline]
161+
pub fn rustc_allow_incoherent_impl(&self) -> bool {
162+
self.flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
163+
}
149164
}
150165

151166
#[derive(Debug, Clone, PartialEq, Eq)]
152167
pub struct TypeAliasData {
153168
pub name: Name,
154169
pub type_ref: Option<TypeRefId>,
155170
pub visibility: RawVisibility,
156-
pub is_extern: bool,
157-
pub rustc_has_incoherent_inherent_impls: bool,
158-
pub rustc_allow_incoherent_impl: bool,
171+
pub flags: TypeAliasFlags,
159172
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
160173
pub bounds: Box<[TypeBound]>,
161174
pub types_map: Arc<TypesMap>,
162175
}
163176

177+
bitflags::bitflags! {
178+
#[derive(Debug, Clone, PartialEq, Eq)]
179+
pub struct TypeAliasFlags: u8 {
180+
const IS_EXTERN = 1 << 0;
181+
const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1;
182+
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 2;
183+
}
184+
}
185+
164186
impl TypeAliasData {
187+
#[inline]
188+
pub fn is_extern(&self) -> bool {
189+
self.flags.contains(TypeAliasFlags::IS_EXTERN)
190+
}
191+
192+
#[inline]
193+
pub fn rustc_has_incoherent_inherent_impls(&self) -> bool {
194+
self.flags.contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
195+
}
196+
197+
#[inline]
198+
pub fn rustc_allow_incoherent_impl(&self) -> bool {
199+
self.flags.contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
200+
}
201+
165202
pub(crate) fn type_alias_data_query(
166203
db: &dyn DefDatabase,
167204
typ: TypeAliasId,
@@ -180,17 +217,24 @@ impl TypeAliasData {
180217
loc.container.module(db).krate(),
181218
ModItem::from(loc.id.value).into(),
182219
);
183-
let rustc_has_incoherent_inherent_impls =
184-
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
185-
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
220+
221+
let mut flags = TypeAliasFlags::empty();
222+
223+
if matches!(loc.container, ItemContainerId::ExternBlockId(_)) {
224+
flags |= TypeAliasFlags::IS_EXTERN;
225+
}
226+
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
227+
flags |= TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS;
228+
}
229+
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
230+
flags |= TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
231+
}
186232

187233
Arc::new(TypeAliasData {
188234
name: typ.name.clone(),
189235
type_ref: typ.type_ref,
190236
visibility,
191-
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
192-
rustc_has_incoherent_inherent_impls,
193-
rustc_allow_incoherent_impl,
237+
flags,
194238
bounds: typ.bounds.clone(),
195239
types_map: typ.types_map.clone(),
196240
})
@@ -199,7 +243,7 @@ impl TypeAliasData {
199243

200244
bitflags::bitflags! {
201245
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
202-
pub struct TraitFlags: u8 {
246+
pub struct TraitFlags: u16 {
203247
const IS_AUTO = 1 << 0;
204248
const IS_UNSAFE = 1 << 1;
205249
const IS_FUNDAMENTAL = 1 << 2;
@@ -332,9 +376,9 @@ impl Macro2Data {
332376
let loc = makro.lookup(db);
333377
let item_tree = loc.id.item_tree(db);
334378
let makro = &item_tree[loc.id.value];
379+
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
335380

336-
let helpers = item_tree
337-
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
381+
let helpers = attrs
338382
.by_key(&sym::rustc_builtin_macro)
339383
.tt_values()
340384
.next()
@@ -362,11 +406,9 @@ impl MacroRulesData {
362406
let loc = makro.lookup(db);
363407
let item_tree = loc.id.item_tree(db);
364408
let makro = &item_tree[loc.id.value];
409+
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
365410

366-
let macro_export = item_tree
367-
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
368-
.by_key(&sym::macro_export)
369-
.exists();
411+
let macro_export = attrs.by_key(&sym::macro_export).exists();
370412

371413
Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
372414
}
@@ -387,11 +429,9 @@ impl ProcMacroData {
387429
let loc = makro.lookup(db);
388430
let item_tree = loc.id.item_tree(db);
389431
let makro = &item_tree[loc.id.value];
432+
let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into());
390433

391-
let (name, helpers) = if let Some(def) = item_tree
392-
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
393-
.parse_proc_macro_decl(&makro.name)
394-
{
434+
let (name, helpers) = if let Some(def) = attrs.parse_proc_macro_decl(&makro.name) {
395435
(
396436
def.name,
397437
match def.kind {
@@ -404,6 +444,7 @@ impl ProcMacroData {
404444
stdx::never!("proc macro declaration is not a proc macro");
405445
(makro.name.clone(), None)
406446
};
447+
407448
Arc::new(ProcMacroData { name, helpers })
408449
}
409450
}
@@ -450,9 +491,16 @@ pub struct ConstData {
450491
pub name: Option<Name>,
451492
pub type_ref: TypeRefId,
452493
pub visibility: RawVisibility,
453-
pub rustc_allow_incoherent_impl: bool,
454-
pub has_body: bool,
455494
pub types_map: Arc<TypesMap>,
495+
pub flags: ConstFlags,
496+
}
497+
498+
bitflags::bitflags! {
499+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500+
pub struct ConstFlags: u8 {
501+
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 0;
502+
const HAS_BODY = 1 << 1;
503+
}
456504
}
457505

458506
impl ConstData {
@@ -465,33 +513,47 @@ impl ConstData {
465513
} else {
466514
item_tree[konst.visibility].clone()
467515
};
516+
let attrs = item_tree.attrs(
517+
db,
518+
loc.container.module(db).krate(),
519+
ModItem::from(loc.id.value).into(),
520+
);
468521

469-
let rustc_allow_incoherent_impl = item_tree
470-
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
471-
.by_key(&sym::rustc_allow_incoherent_impl)
472-
.exists();
522+
let mut flags = ConstFlags::empty();
523+
if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() {
524+
flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL;
525+
}
526+
if konst.has_body {
527+
flags |= ConstFlags::HAS_BODY;
528+
}
473529

474530
Arc::new(ConstData {
475531
name: konst.name.clone(),
476532
type_ref: konst.type_ref,
477533
visibility,
478-
rustc_allow_incoherent_impl,
479-
has_body: konst.has_body,
534+
flags,
480535
types_map: konst.types_map.clone(),
481536
})
482537
}
538+
539+
#[inline]
540+
pub fn rustc_allow_incoherent_impl(&self) -> bool {
541+
self.flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
542+
}
543+
544+
#[inline]
545+
pub fn has_body(&self) -> bool {
546+
self.flags.contains(ConstFlags::HAS_BODY)
547+
}
483548
}
484549

485550
#[derive(Debug, Clone, PartialEq, Eq)]
486551
pub struct StaticData {
487552
pub name: Name,
488553
pub type_ref: TypeRefId,
489554
pub visibility: RawVisibility,
490-
pub mutable: bool,
491-
pub is_extern: bool,
492-
pub has_safe_kw: bool,
493-
pub has_unsafe_kw: bool,
494555
pub types_map: Arc<TypesMap>,
556+
pub flags: StaticFlags,
495557
}
496558

497559
impl StaticData {
@@ -500,17 +562,39 @@ impl StaticData {
500562
let item_tree = loc.id.item_tree(db);
501563
let statik = &item_tree[loc.id.value];
502564

565+
let mut flags = statik.flags;
566+
if matches!(loc.container, ItemContainerId::ExternBlockId(_)) {
567+
flags |= StaticFlags::IS_EXTERN;
568+
}
569+
503570
Arc::new(StaticData {
504571
name: statik.name.clone(),
505572
type_ref: statik.type_ref,
506573
visibility: item_tree[statik.visibility].clone(),
507-
mutable: statik.mutable,
508-
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
509-
has_safe_kw: statik.has_safe_kw,
510-
has_unsafe_kw: statik.has_unsafe_kw,
574+
flags,
511575
types_map: statik.types_map.clone(),
512576
})
513577
}
578+
579+
#[inline]
580+
pub fn is_extern(&self) -> bool {
581+
self.flags.contains(StaticFlags::IS_EXTERN)
582+
}
583+
584+
#[inline]
585+
pub fn mutable(&self) -> bool {
586+
self.flags.contains(StaticFlags::MUTABLE)
587+
}
588+
589+
#[inline]
590+
pub fn has_safe_kw(&self) -> bool {
591+
self.flags.contains(StaticFlags::HAS_SAFE_KW)
592+
}
593+
594+
#[inline]
595+
pub fn has_unsafe_kw(&self) -> bool {
596+
self.flags.contains(StaticFlags::HAS_UNSAFE_KW)
597+
}
514598
}
515599

516600
fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility {

crates/hir-def/src/data/adt.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ impl StructData {
225225
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
226226
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
227227
let mut flags = StructFlags::NO_FLAGS;
228+
228229
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
229230
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
230231
}
@@ -289,10 +290,10 @@ impl EnumData {
289290
let krate = loc.container.krate;
290291
let item_tree = loc.id.item_tree(db);
291292
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
292-
let rustc_has_incoherent_inherent_impls = item_tree
293-
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
294-
.by_key(&sym::rustc_has_incoherent_inherent_impls)
295-
.exists();
293+
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
294+
295+
let rustc_has_incoherent_inherent_impls =
296+
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
296297

297298
let enum_ = &item_tree[loc.id.value];
298299

0 commit comments

Comments
 (0)