Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 102 |
1 files changed, 100 insertions, 2 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 24323284e9..9b8c7b900a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1187,6 +1187,10 @@ impl Struct { fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { db.struct_data(self.id).variant_data.clone() } + + pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { + db.attrs(self.id.into()).is_unstable() + } } impl HasVisibility for Struct { @@ -1229,6 +1233,10 @@ impl Union { fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { db.union_data(self.id).variant_data.clone() } + + pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { + db.attrs(self.id.into()).is_unstable() + } } impl HasVisibility for Union { @@ -1318,6 +1326,10 @@ impl Enum { pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { Adt::from(self).layout(db) } + + pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { + db.attrs(self.id.into()).is_unstable() + } } impl HasVisibility for Enum { @@ -1393,6 +1405,10 @@ impl Variant { _ => parent_layout, }) } + + pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { + db.attrs(self.id.into()).is_unstable() + } } /// Variants inherit visibility from the parent enum. @@ -2912,7 +2928,7 @@ impl GenericDef { .collect() } - pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> { + pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> { let generics = db.generic_params(self.into()); generics .type_or_consts @@ -2922,6 +2938,40 @@ impl GenericDef { }) .collect() } + + pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { + let generics = db.generic_params(self.into()); + generics + .type_or_consts + .iter() + .filter_map(|(local_id, data)| match data { + hir_def::generics::TypeOrConstParamData::TypeParamData(_) => Some(TypeParam { + id: TypeParamId::from_unchecked(TypeOrConstParamId { + parent: self.into(), + local_id, + }), + }), + hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None, + }) + .collect() + } + + pub fn const_params(self, db: &dyn HirDatabase) -> Vec<ConstParam> { + let generics = db.generic_params(self.into()); + generics + .type_or_consts + .iter() + .filter_map(|(local_id, data)| match data { + hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None, + hir_def::generics::TypeOrConstParamData::ConstParamData(_) => Some(ConstParam { + id: ConstParamId::from_unchecked(TypeOrConstParamId { + parent: self.into(), + local_id, + }), + }), + }) + .collect() + } } /// A single local definition. @@ -3284,12 +3334,16 @@ impl TypeParam { let ty = generic_arg_from_param(db, self.id.into())?; let resolver = self.id.parent().resolver(db.upcast()); match ty.data(Interner) { - GenericArgData::Ty(it) => { + GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => { Some(Type::new_with_resolver_inner(db, &resolver, it.clone())) } _ => None, } } + + pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { + db.attrs(GenericParamId::from(self.id).into()).is_unstable() + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -3773,6 +3827,50 @@ impl Type { matches!(self.ty.kind(Interner), TyKind::Ref(..)) } + pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool { + return go(db, self.env.krate, &self.ty); + + fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool { + match ty.kind(Interner) { + // Reference itself + TyKind::Ref(_, _, _) => true, + + // For non-phantom_data adts we check variants/fields as well as generic parameters + TyKind::Adt(adt_id, substitution) + if !db.struct_datum(krate, *adt_id).flags.phantom_data => + { + let adt_datum = &db.struct_datum(krate, *adt_id); + let adt_datum_bound = + adt_datum.binders.clone().substitute(Interner, substitution); + adt_datum_bound + .variants + .into_iter() + .flat_map(|variant| variant.fields.into_iter()) + .any(|ty| go(db, krate, &ty)) + || substitution + .iter(Interner) + .filter_map(|x| x.ty(Interner)) + .any(|ty| go(db, krate, ty)) + } + // And for `PhantomData<T>`, we check `T`. + TyKind::Adt(_, substitution) + | TyKind::Tuple(_, substitution) + | TyKind::OpaqueType(_, substitution) + | TyKind::AssociatedType(_, substitution) + | TyKind::FnDef(_, substitution) => substitution + .iter(Interner) + .filter_map(|x| x.ty(Interner)) + .any(|ty| go(db, krate, ty)), + + // For `[T]` or `*T` we check `T` + TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty), + + // Consider everything else as not reference + _ => false, + } + } + } + pub fn as_reference(&self) -> Option<(Type, Mutability)> { let (ty, _lt, m) = self.ty.as_reference()?; let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut)); |