Skip to content

Commit 5e079c0

Browse files
committed
Add static method tactic
1 parent b55af44 commit 5e079c0

File tree

8 files changed

+569
-93
lines changed

8 files changed

+569
-93
lines changed

crates/hir-def/src/attr.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -382,27 +382,36 @@ impl AttrsWithOwner {
382382
AttrDefId::GenericParamId(it) => match it {
383383
GenericParamId::ConstParamId(it) => {
384384
let src = it.parent().child_source(db);
385-
RawAttrs::from_attrs_owner(
386-
db.upcast(),
387-
src.with_value(&src.value[it.local_id()]),
388-
db.span_map(src.file_id).as_ref(),
389-
)
385+
match src.value.get(it.local_id()) {
386+
Some(val) => RawAttrs::from_attrs_owner(
387+
db.upcast(),
388+
src.with_value(val),
389+
db.span_map(src.file_id).as_ref(),
390+
),
391+
None => RawAttrs::EMPTY,
392+
}
390393
}
391394
GenericParamId::TypeParamId(it) => {
392395
let src = it.parent().child_source(db);
393-
RawAttrs::from_attrs_owner(
394-
db.upcast(),
395-
src.with_value(&src.value[it.local_id()]),
396-
db.span_map(src.file_id).as_ref(),
397-
)
396+
match src.value.get(it.local_id()) {
397+
Some(val) => RawAttrs::from_attrs_owner(
398+
db.upcast(),
399+
src.with_value(val),
400+
db.span_map(src.file_id).as_ref(),
401+
),
402+
None => RawAttrs::EMPTY,
403+
}
398404
}
399405
GenericParamId::LifetimeParamId(it) => {
400406
let src = it.parent.child_source(db);
401-
RawAttrs::from_attrs_owner(
402-
db.upcast(),
403-
src.with_value(&src.value[it.local_id]),
404-
db.span_map(src.file_id).as_ref(),
405-
)
407+
match src.value.get(it.local_id) {
408+
Some(val) => RawAttrs::from_attrs_owner(
409+
db.upcast(),
410+
src.with_value(val),
411+
db.span_map(src.file_id).as_ref(),
412+
),
413+
None => RawAttrs::EMPTY,
414+
}
406415
}
407416
},
408417
AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it),

crates/hir/src/lib.rs

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,10 @@ impl Struct {
11911191
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
11921192
db.struct_data(self.id).variant_data.clone()
11931193
}
1194+
1195+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1196+
db.attrs(self.id.into()).is_unstable()
1197+
}
11941198
}
11951199

11961200
impl HasVisibility for Struct {
@@ -1233,6 +1237,10 @@ impl Union {
12331237
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
12341238
db.union_data(self.id).variant_data.clone()
12351239
}
1240+
1241+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1242+
db.attrs(self.id.into()).is_unstable()
1243+
}
12361244
}
12371245

12381246
impl HasVisibility for Union {
@@ -1322,6 +1330,10 @@ impl Enum {
13221330
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
13231331
Adt::from(self).layout(db)
13241332
}
1333+
1334+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1335+
db.attrs(self.id.into()).is_unstable()
1336+
}
13251337
}
13261338

13271339
impl HasVisibility for Enum {
@@ -1397,6 +1409,10 @@ impl Variant {
13971409
_ => parent_layout,
13981410
})
13991411
}
1412+
1413+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1414+
db.variants_attrs(self.parent.into())[self.id].is_unstable()
1415+
}
14001416
}
14011417

14021418
/// Variants inherit visibility from the parent enum.
@@ -3143,7 +3159,7 @@ impl GenericDef {
31433159
.collect()
31443160
}
31453161

3146-
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
3162+
pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
31473163
let generics = db.generic_params(self.into());
31483164
generics
31493165
.type_or_consts
@@ -3153,6 +3169,40 @@ impl GenericDef {
31533169
})
31543170
.collect()
31553171
}
3172+
3173+
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
3174+
let generics = db.generic_params(self.into());
3175+
generics
3176+
.type_or_consts
3177+
.iter()
3178+
.filter_map(|(local_id, data)| match data {
3179+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => Some(TypeParam {
3180+
id: TypeParamId::from_unchecked(TypeOrConstParamId {
3181+
parent: self.into(),
3182+
local_id,
3183+
}),
3184+
}),
3185+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None,
3186+
})
3187+
.collect()
3188+
}
3189+
3190+
pub fn const_params(self, db: &dyn HirDatabase) -> Vec<ConstParam> {
3191+
let generics = db.generic_params(self.into());
3192+
generics
3193+
.type_or_consts
3194+
.iter()
3195+
.filter_map(|(local_id, data)| match data {
3196+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
3197+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => Some(ConstParam {
3198+
id: ConstParamId::from_unchecked(TypeOrConstParamId {
3199+
parent: self.into(),
3200+
local_id,
3201+
}),
3202+
}),
3203+
})
3204+
.collect()
3205+
}
31563206
}
31573207

31583208
/// A single local definition.
@@ -3515,12 +3565,16 @@ impl TypeParam {
35153565
let ty = generic_arg_from_param(db, self.id.into())?;
35163566
let resolver = self.id.parent().resolver(db.upcast());
35173567
match ty.data(Interner) {
3518-
GenericArgData::Ty(it) => {
3568+
GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => {
35193569
Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
35203570
}
35213571
_ => None,
35223572
}
35233573
}
3574+
3575+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
3576+
db.attrs(GenericParamId::from(self.id).into()).is_unstable()
3577+
}
35243578
}
35253579

35263580
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -4004,6 +4058,50 @@ impl Type {
40044058
matches!(self.ty.kind(Interner), TyKind::Ref(..))
40054059
}
40064060

4061+
pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
4062+
return go(db, self.env.krate, &self.ty);
4063+
4064+
fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
4065+
match ty.kind(Interner) {
4066+
// Reference itself
4067+
TyKind::Ref(_, _, _) => true,
4068+
4069+
// For non-phantom_data adts we check variants/fields as well as generic parameters
4070+
TyKind::Adt(adt_id, substitution)
4071+
if !db.struct_datum(krate, *adt_id).flags.phantom_data =>
4072+
{
4073+
let adt_datum = &db.struct_datum(krate, *adt_id);
4074+
let adt_datum_bound =
4075+
adt_datum.binders.clone().substitute(Interner, substitution);
4076+
adt_datum_bound
4077+
.variants
4078+
.into_iter()
4079+
.flat_map(|variant| variant.fields.into_iter())
4080+
.any(|ty| go(db, krate, &ty))
4081+
|| substitution
4082+
.iter(Interner)
4083+
.filter_map(|x| x.ty(Interner))
4084+
.any(|ty| go(db, krate, ty))
4085+
}
4086+
// And for `PhantomData<T>`, we check `T`.
4087+
TyKind::Adt(_, substitution)
4088+
| TyKind::Tuple(_, substitution)
4089+
| TyKind::OpaqueType(_, substitution)
4090+
| TyKind::AssociatedType(_, substitution)
4091+
| TyKind::FnDef(_, substitution) => substitution
4092+
.iter(Interner)
4093+
.filter_map(|x| x.ty(Interner))
4094+
.any(|ty| go(db, krate, ty)),
4095+
4096+
// For `[T]` or `*T` we check `T`
4097+
TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty),
4098+
4099+
// Consider everything else as not reference
4100+
_ => false,
4101+
}
4102+
}
4103+
}
4104+
40074105
pub fn as_reference(&self) -> Option<(Type, Mutability)> {
40084106
let (ty, _lt, m) = self.ty.as_reference()?;
40094107
let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));

crates/hir/src/term_search/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct LookupTable {
4747
round_scopedef_hits: FxHashSet<ScopeDef>,
4848
/// Amount of rounds since scopedef was first used.
4949
rounds_since_sopedef_hit: FxHashMap<ScopeDef, u32>,
50+
/// Types queried but not present
51+
types_wishlist: FxHashSet<Type>,
5052
}
5153

5254
impl LookupTable {
@@ -149,6 +151,10 @@ impl LookupTable {
149151
fn exhausted_scopedefs(&self) -> &FxHashSet<ScopeDef> {
150152
&self.exhausted_scopedefs
151153
}
154+
155+
fn take_types_wishlist(&mut self) -> FxHashSet<Type> {
156+
std::mem::take(&mut self.types_wishlist)
157+
}
152158
}
153159

154160
/// # Term search
@@ -205,6 +211,7 @@ pub fn term_search<DB: HirDatabase>(
205211
solutions.extend(tactics::free_function(sema.db, &module, &defs, &mut lookup, goal));
206212
solutions.extend(tactics::impl_method(sema.db, &module, &defs, &mut lookup, goal));
207213
solutions.extend(tactics::struct_projection(sema.db, &module, &defs, &mut lookup, goal));
214+
solutions.extend(tactics::impl_static_method(sema.db, &module, &defs, &mut lookup, goal));
208215

209216
// Break after 1 round after successful solution
210217
if solution_found {

0 commit comments

Comments
 (0)