Skip to content

Commit 627255d

Browse files
committed
Add static method tactic
1 parent 35eb0db commit 627255d

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
@@ -377,27 +377,36 @@ impl AttrsWithOwner {
377377
AttrDefId::GenericParamId(it) => match it {
378378
GenericParamId::ConstParamId(it) => {
379379
let src = it.parent().child_source(db);
380-
RawAttrs::from_attrs_owner(
381-
db.upcast(),
382-
src.with_value(&src.value[it.local_id()]),
383-
db.span_map(src.file_id).as_ref(),
384-
)
380+
match src.value.get(it.local_id()) {
381+
Some(val) => RawAttrs::from_attrs_owner(
382+
db.upcast(),
383+
src.with_value(val),
384+
db.span_map(src.file_id).as_ref(),
385+
),
386+
None => RawAttrs::EMPTY,
387+
}
385388
}
386389
GenericParamId::TypeParamId(it) => {
387390
let src = it.parent().child_source(db);
388-
RawAttrs::from_attrs_owner(
389-
db.upcast(),
390-
src.with_value(&src.value[it.local_id()]),
391-
db.span_map(src.file_id).as_ref(),
392-
)
391+
match src.value.get(it.local_id()) {
392+
Some(val) => RawAttrs::from_attrs_owner(
393+
db.upcast(),
394+
src.with_value(val),
395+
db.span_map(src.file_id).as_ref(),
396+
),
397+
None => RawAttrs::EMPTY,
398+
}
393399
}
394400
GenericParamId::LifetimeParamId(it) => {
395401
let src = it.parent.child_source(db);
396-
RawAttrs::from_attrs_owner(
397-
db.upcast(),
398-
src.with_value(&src.value[it.local_id]),
399-
db.span_map(src.file_id).as_ref(),
400-
)
402+
match src.value.get(it.local_id) {
403+
Some(val) => RawAttrs::from_attrs_owner(
404+
db.upcast(),
405+
src.with_value(val),
406+
db.span_map(src.file_id).as_ref(),
407+
),
408+
None => RawAttrs::EMPTY,
409+
}
401410
}
402411
},
403412
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
@@ -1187,6 +1187,10 @@ impl Struct {
11871187
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
11881188
db.struct_data(self.id).variant_data.clone()
11891189
}
1190+
1191+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1192+
db.attrs(self.id.into()).is_unstable()
1193+
}
11901194
}
11911195

11921196
impl HasVisibility for Struct {
@@ -1229,6 +1233,10 @@ impl Union {
12291233
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
12301234
db.union_data(self.id).variant_data.clone()
12311235
}
1236+
1237+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1238+
db.attrs(self.id.into()).is_unstable()
1239+
}
12321240
}
12331241

12341242
impl HasVisibility for Union {
@@ -1318,6 +1326,10 @@ impl Enum {
13181326
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
13191327
Adt::from(self).layout(db)
13201328
}
1329+
1330+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1331+
db.attrs(self.id.into()).is_unstable()
1332+
}
13211333
}
13221334

13231335
impl HasVisibility for Enum {
@@ -1393,6 +1405,10 @@ impl Variant {
13931405
_ => parent_layout,
13941406
})
13951407
}
1408+
1409+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
1410+
db.attrs(self.id.into()).is_unstable()
1411+
}
13961412
}
13971413

13981414
/// Variants inherit visibility from the parent enum.
@@ -2912,7 +2928,7 @@ impl GenericDef {
29122928
.collect()
29132929
}
29142930

2915-
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
2931+
pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
29162932
let generics = db.generic_params(self.into());
29172933
generics
29182934
.type_or_consts
@@ -2922,6 +2938,40 @@ impl GenericDef {
29222938
})
29232939
.collect()
29242940
}
2941+
2942+
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
2943+
let generics = db.generic_params(self.into());
2944+
generics
2945+
.type_or_consts
2946+
.iter()
2947+
.filter_map(|(local_id, data)| match data {
2948+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => Some(TypeParam {
2949+
id: TypeParamId::from_unchecked(TypeOrConstParamId {
2950+
parent: self.into(),
2951+
local_id,
2952+
}),
2953+
}),
2954+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None,
2955+
})
2956+
.collect()
2957+
}
2958+
2959+
pub fn const_params(self, db: &dyn HirDatabase) -> Vec<ConstParam> {
2960+
let generics = db.generic_params(self.into());
2961+
generics
2962+
.type_or_consts
2963+
.iter()
2964+
.filter_map(|(local_id, data)| match data {
2965+
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
2966+
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => Some(ConstParam {
2967+
id: ConstParamId::from_unchecked(TypeOrConstParamId {
2968+
parent: self.into(),
2969+
local_id,
2970+
}),
2971+
}),
2972+
})
2973+
.collect()
2974+
}
29252975
}
29262976

29272977
/// A single local definition.
@@ -3284,12 +3334,16 @@ impl TypeParam {
32843334
let ty = generic_arg_from_param(db, self.id.into())?;
32853335
let resolver = self.id.parent().resolver(db.upcast());
32863336
match ty.data(Interner) {
3287-
GenericArgData::Ty(it) => {
3337+
GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => {
32883338
Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
32893339
}
32903340
_ => None,
32913341
}
32923342
}
3343+
3344+
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
3345+
db.attrs(GenericParamId::from(self.id).into()).is_unstable()
3346+
}
32933347
}
32943348

32953349
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -3773,6 +3827,50 @@ impl Type {
37733827
matches!(self.ty.kind(Interner), TyKind::Ref(..))
37743828
}
37753829

3830+
pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
3831+
return go(db, self.env.krate, &self.ty);
3832+
3833+
fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
3834+
match ty.kind(Interner) {
3835+
// Reference itself
3836+
TyKind::Ref(_, _, _) => true,
3837+
3838+
// For non-phantom_data adts we check variants/fields as well as generic parameters
3839+
TyKind::Adt(adt_id, substitution)
3840+
if !db.struct_datum(krate, *adt_id).flags.phantom_data =>
3841+
{
3842+
let adt_datum = &db.struct_datum(krate, *adt_id);
3843+
let adt_datum_bound =
3844+
adt_datum.binders.clone().substitute(Interner, substitution);
3845+
adt_datum_bound
3846+
.variants
3847+
.into_iter()
3848+
.flat_map(|variant| variant.fields.into_iter())
3849+
.any(|ty| go(db, krate, &ty))
3850+
|| substitution
3851+
.iter(Interner)
3852+
.filter_map(|x| x.ty(Interner))
3853+
.any(|ty| go(db, krate, ty))
3854+
}
3855+
// And for `PhantomData<T>`, we check `T`.
3856+
TyKind::Adt(_, substitution)
3857+
| TyKind::Tuple(_, substitution)
3858+
| TyKind::OpaqueType(_, substitution)
3859+
| TyKind::AssociatedType(_, substitution)
3860+
| TyKind::FnDef(_, substitution) => substitution
3861+
.iter(Interner)
3862+
.filter_map(|x| x.ty(Interner))
3863+
.any(|ty| go(db, krate, ty)),
3864+
3865+
// For `[T]` or `*T` we check `T`
3866+
TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty),
3867+
3868+
// Consider everything else as not reference
3869+
_ => false,
3870+
}
3871+
}
3872+
}
3873+
37763874
pub fn as_reference(&self) -> Option<(Type, Mutability)> {
37773875
let (ty, _lt, m) = self.ty.as_reference()?;
37783876
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)