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.rs125
1 files changed, 90 insertions, 35 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index e02ba2e7c8..45a4c6a50e 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -50,7 +50,7 @@ use hir_def::{
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
- TypeParamId, UnionId,
+ TypeOrConstParamId, TypeParamId, UnionId,
};
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind};
use hir_ty::{
@@ -71,7 +71,7 @@ use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
use once_cell::unsync::Lazy;
use rustc_hash::FxHashSet;
-use stdx::{format_to, impl_from};
+use stdx::{format_to, impl_from, never};
use syntax::{
ast::{self, HasAttrs as _, HasDocComments, HasName},
AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
@@ -2007,11 +2007,13 @@ impl_from!(
impl GenericDef {
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
let generics = db.generic_params(self.into());
- let ty_params = generics
- .types
- .iter()
- .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
- .map(GenericParam::TypeParam);
+ let ty_params = generics.types.iter().map(|(local_id, _)| {
+ let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
+ match toc.split(db) {
+ Either::Left(x) => GenericParam::ConstParam(x),
+ Either::Right(x) => GenericParam::TypeParam(x),
+ }
+ });
let lt_params = generics
.lifetimes
.iter()
@@ -2019,20 +2021,17 @@ impl GenericDef {
id: LifetimeParamId { parent: self.into(), local_id },
})
.map(GenericParam::LifetimeParam);
- let const_params = generics
- .consts
- .iter()
- .map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } })
- .map(GenericParam::ConstParam);
- ty_params.chain(lt_params).chain(const_params).collect()
+ ty_params.chain(lt_params).collect()
}
- pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
+ pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
let generics = db.generic_params(self.into());
generics
.types
.iter()
- .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
+ .map(|(local_id, _)| TypeOrConstParam {
+ id: TypeOrConstParamId { parent: self.into(), local_id },
+ })
.collect()
}
}
@@ -2221,25 +2220,25 @@ impl Label {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum GenericParam {
TypeParam(TypeParam),
- LifetimeParam(LifetimeParam),
ConstParam(ConstParam),
+ LifetimeParam(LifetimeParam),
}
-impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam);
+impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
impl GenericParam {
pub fn module(self, db: &dyn HirDatabase) -> Module {
match self {
GenericParam::TypeParam(it) => it.module(db),
- GenericParam::LifetimeParam(it) => it.module(db),
GenericParam::ConstParam(it) => it.module(db),
+ GenericParam::LifetimeParam(it) => it.module(db),
}
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
match self {
GenericParam::TypeParam(it) => it.name(db),
- GenericParam::LifetimeParam(it) => it.name(db),
GenericParam::ConstParam(it) => it.name(db),
+ GenericParam::LifetimeParam(it) => it.name(db),
}
}
}
@@ -2250,19 +2249,23 @@ pub struct TypeParam {
}
impl TypeParam {
+ pub fn merge(self) -> TypeOrConstParam {
+ TypeOrConstParam { id: self.id.into() }
+ }
+
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let params = db.generic_params(self.id.parent);
- params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing)
+ self.merge().name(db)
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
- self.id.parent.module(db.upcast()).into()
+ self.id.parent().module(db.upcast()).into()
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- let resolver = self.id.parent.resolver(db.upcast());
- let krate = self.id.parent.module(db.upcast()).krate();
- let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(Interner);
+ let resolver = self.id.parent().resolver(db.upcast());
+ let krate = self.id.parent().module(db.upcast()).krate();
+ let ty =
+ TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
Type::new_with_resolver_inner(db, krate, &resolver, ty)
}
@@ -2270,7 +2273,7 @@ impl TypeParam {
/// parameter, not additional bounds that might be added e.g. by a method if
/// the parameter comes from an impl!
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
- db.generic_predicates_for_param(self.id.parent, self.id, None)
+ db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
.iter()
.filter_map(|pred| match &pred.skip_binders().skip_binders() {
hir_ty::WhereClause::Implemented(trait_ref) => {
@@ -2282,12 +2285,12 @@ impl TypeParam {
}
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
- let params = db.generic_defaults(self.id.parent);
- let local_idx = hir_ty::param_idx(db, self.id)?;
- let resolver = self.id.parent.resolver(db.upcast());
- let krate = self.id.parent.module(db.upcast()).krate();
+ let params = db.generic_defaults(self.id.parent());
+ let local_idx = hir_ty::param_idx(db, self.id.into())?;
+ let resolver = self.id.parent().resolver(db.upcast());
+ let krate = self.id.parent().module(db.upcast()).krate();
let ty = params.get(local_idx)?.clone();
- let subst = TyBuilder::type_params_subst(db, self.id.parent);
+ let subst = TyBuilder::type_params_subst(db, self.id.parent());
let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
}
@@ -2319,9 +2322,48 @@ pub struct ConstParam {
}
impl ConstParam {
+ pub fn merge(self) -> TypeOrConstParam {
+ TypeOrConstParam { id: self.id.into() }
+ }
+
+ pub fn name(self, db: &dyn HirDatabase) -> Name {
+ let params = db.generic_params(self.id.parent());
+ match params.types[self.id.local_id()].name() {
+ Some(x) => x.clone(),
+ None => {
+ never!();
+ Name::missing()
+ }
+ }
+ }
+
+ pub fn module(self, db: &dyn HirDatabase) -> Module {
+ self.id.parent().module(db.upcast()).into()
+ }
+
+ pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
+ self.id.parent().into()
+ }
+
+ pub fn ty(self, db: &dyn HirDatabase) -> Type {
+ let def = self.id.parent();
+ let krate = def.module(db.upcast()).krate();
+ Type::new(db, krate, def, db.const_param_ty(self.id))
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct TypeOrConstParam {
+ pub(crate) id: TypeOrConstParamId,
+}
+
+impl TypeOrConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent);
- params.consts[self.id.local_id].name.clone()
+ match params.types[self.id.local_id].name() {
+ Some(n) => n.clone(),
+ _ => Name::missing(),
+ }
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -2332,10 +2374,23 @@ impl ConstParam {
self.id.parent.into()
}
+ pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
+ let params = db.generic_params(self.id.parent);
+ match &params.types[self.id.local_id] {
+ hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
+ Either::Right(TypeParam { id: self.id.into() })
+ }
+ hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
+ Either::Left(ConstParam { id: self.id.into() })
+ }
+ }
+ }
+
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- let def = self.id.parent;
- let krate = def.module(db.upcast()).krate();
- Type::new(db, krate, def, db.const_param_ty(self.id))
+ match self.split(db) {
+ Either::Left(x) => x.ty(db),
+ Either::Right(x) => x.ty(db),
+ }
}
}