Skip to content

Commit fa93910

Browse files
committed
Add static method tactic
1 parent b00ff5f commit fa93910

File tree

8 files changed

+566
-93
lines changed

8 files changed

+566
-93
lines changed

crates/hir-def/src/attr.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -418,27 +418,36 @@ impl AttrsWithOwner {
418418
AttrDefId::GenericParamId(it) => match it {
419419
GenericParamId::ConstParamId(it) => {
420420
let src = it.parent().child_source(db);
421-
RawAttrs::from_attrs_owner(
422-
db.upcast(),
423-
src.with_value(&src.value[it.local_id()]),
424-
db.span_map(src.file_id).as_ref(),
425-
)
421+
match src.value.get(it.local_id()) {
422+
Some(val) => RawAttrs::from_attrs_owner(
423+
db.upcast(),
424+
src.with_value(val),
425+
db.span_map(src.file_id).as_ref(),
426+
),
427+
None => RawAttrs::EMPTY,
428+
}
426429
}
427430
GenericParamId::TypeParamId(it) => {
428431
let src = it.parent().child_source(db);
429-
RawAttrs::from_attrs_owner(
430-
db.upcast(),
431-
src.with_value(&src.value[it.local_id()]),
432-
db.span_map(src.file_id).as_ref(),
433-
)
432+
match src.value.get(it.local_id()) {
433+
Some(val) => RawAttrs::from_attrs_owner(
434+
db.upcast(),
435+
src.with_value(val),
436+
db.span_map(src.file_id).as_ref(),
437+
),
438+
None => RawAttrs::EMPTY,
439+
}
434440
}
435441
GenericParamId::LifetimeParamId(it) => {
436442
let src = it.parent.child_source(db);
437-
RawAttrs::from_attrs_owner(
438-
db.upcast(),
439-
src.with_value(&src.value[it.local_id]),
440-
db.span_map(src.file_id).as_ref(),
441-
)
443+
match src.value.get(it.local_id) {
444+
Some(val) => RawAttrs::from_attrs_owner(
445+
db.upcast(),
446+
src.with_value(val),
447+
db.span_map(src.file_id).as_ref(),
448+
),
449+
None => RawAttrs::EMPTY,
450+
}
442451
}
443452
},
444453
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
@@ -1170,6 +1170,10 @@ impl Struct {
11701170
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
11711171
db.struct_data(self.id).variant_data.clone()
11721172
}
1173+
1174+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1175+
db.attrs(self.id.into()).is_unstable()
1176+
}
11731177
}
11741178

11751179
impl HasVisibility for Struct {
@@ -1212,6 +1216,10 @@ impl Union {
12121216
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
12131217
db.union_data(self.id).variant_data.clone()
12141218
}
1219+
1220+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1221+
db.attrs(self.id.into()).is_unstable()
1222+
}
12151223
}
12161224

12171225
impl HasVisibility for Union {
@@ -1301,6 +1309,10 @@ impl Enum {
13011309
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
13021310
Adt::from(self).layout(db)
13031311
}
1312+
1313+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1314+
db.attrs(self.id.into()).is_unstable()
1315+
}
13041316
}
13051317

13061318
impl HasVisibility for Enum {
@@ -1373,6 +1385,10 @@ impl Variant {
13731385
_ => parent_layout,
13741386
})
13751387
}
1388+
1389+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1390+
db.variants_attrs(self.parent.into())[self.id].is_unstable()
1391+
}
13761392
}
13771393

13781394
/// Variants inherit visibility from the parent enum.
@@ -3081,7 +3097,7 @@ impl GenericDef {
30813097
.collect()
30823098
}
30833099

3084-
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
3100+
pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
30853101
let generics = db.generic_params(self.into());
30863102
generics
30873103
.type_or_consts
@@ -3091,6 +3107,40 @@ impl GenericDef {
30913107
})
30923108
.collect()
30933109
}
3110+
3111+
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
3112+
let generics = db.generic_params(self.into());
3113+
generics
3114+
.type_or_consts
3115+
.iter()
3116+
.filter_map(|(local_id, data)| match data {
3117+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => Some(TypeParam {
3118+
id: TypeParamId::from_unchecked(TypeOrConstParamId {
3119+
parent: self.into(),
3120+
local_id,
3121+
}),
3122+
}),
3123+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None,
3124+
})
3125+
.collect()
3126+
}
3127+
3128+
pub fn const_params(self, db: &dyn HirDatabase) -> Vec<ConstParam> {
3129+
let generics = db.generic_params(self.into());
3130+
generics
3131+
.type_or_consts
3132+
.iter()
3133+
.filter_map(|(local_id, data)| match data {
3134+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
3135+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => Some(ConstParam {
3136+
id: ConstParamId::from_unchecked(TypeOrConstParamId {
3137+
parent: self.into(),
3138+
local_id,
3139+
}),
3140+
}),
3141+
})
3142+
.collect()
3143+
}
30943144
}
30953145

30963146
/// A single local definition.
@@ -3452,12 +3502,16 @@ impl TypeParam {
34523502
let ty = generic_arg_from_param(db, self.id.into())?;
34533503
let resolver = self.id.parent().resolver(db.upcast());
34543504
match ty.data(Interner) {
3455-
GenericArgData::Ty(it) => {
3505+
GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => {
34563506
Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
34573507
}
34583508
_ => None,
34593509
}
34603510
}
3511+
3512+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
3513+
db.attrs(GenericParamId::from(self.id).into()).is_unstable()
3514+
}
34613515
}
34623516

34633517
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -3940,6 +3994,50 @@ impl Type {
39403994
matches!(self.ty.kind(Interner), TyKind::Ref(..))
39413995
}
39423996

3997+
pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
3998+
return go(db, self.env.krate, &self.ty);
3999+
4000+
fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
4001+
match ty.kind(Interner) {
4002+
// Reference itself
4003+
TyKind::Ref(_, _, _) => true,
4004+
4005+
// For non-phantom_data adts we check variants/fields as well as generic parameters
4006+
TyKind::Adt(adt_id, substitution)
4007+
if !db.struct_datum(krate, *adt_id).flags.phantom_data =>
4008+
{
4009+
let adt_datum = &db.struct_datum(krate, *adt_id);
4010+
let adt_datum_bound =
4011+
adt_datum.binders.clone().substitute(Interner, substitution);
4012+
adt_datum_bound
4013+
.variants
4014+
.into_iter()
4015+
.flat_map(|variant| variant.fields.into_iter())
4016+
.any(|ty| go(db, krate, &ty))
4017+
|| substitution
4018+
.iter(Interner)
4019+
.filter_map(|x| x.ty(Interner))
4020+
.any(|ty| go(db, krate, ty))
4021+
}
4022+
// And for `PhantomData<T>`, we check `T`.
4023+
TyKind::Adt(_, substitution)
4024+
| TyKind::Tuple(_, substitution)
4025+
| TyKind::OpaqueType(_, substitution)
4026+
| TyKind::AssociatedType(_, substitution)
4027+
| TyKind::FnDef(_, substitution) => substitution
4028+
.iter(Interner)
4029+
.filter_map(|x| x.ty(Interner))
4030+
.any(|ty| go(db, krate, ty)),
4031+
4032+
// For `[T]` or `*T` we check `T`
4033+
TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty),
4034+
4035+
// Consider everything else as not reference
4036+
_ => false,
4037+
}
4038+
}
4039+
}
4040+
39434041
pub fn as_reference(&self) -> Option<(Type, Mutability)> {
39444042
let (ty, _lt, m) = self.ty.as_reference()?;
39454043
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)