about summary refs log tree commit diff
diff options
context:
space:
mode:
authordfireBird <me@dfirebird.dev>2024-03-09 01:08:35 +0530
committerdfireBird <me@dfirebird.dev>2024-03-18 17:18:08 +0530
commita6c8cbfd9116226541e91528e6a20c26d52ead46 (patch)
tree0270378e218986f622a8653232ae3eccd76262a1
parentd6e3929841cbf78adff4e2edb0f6005919ad3a35 (diff)
downloadrust-a6c8cbfd9116226541e91528e6a20c26d52ead46.tar.gz
rust-a6c8cbfd9116226541e91528e6a20c26d52ead46.zip
update `Generics` iter methods to return `GenericParamId`
-rw-r--r--crates/hir-def/src/generics.rs40
-rw-r--r--crates/hir-ty/src/builder.rs19
-rw-r--r--crates/hir-ty/src/infer/expr.rs21
-rw-r--r--crates/hir-ty/src/lib.rs2
-rw-r--r--crates/hir-ty/src/lower.rs49
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs12
-rw-r--r--crates/hir-ty/src/utils.rs149
7 files changed, 181 insertions, 111 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 8bdd9c6587d..c141acd2ec4 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -102,6 +102,46 @@ impl TypeOrConstParamData {
 
 impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
 
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericParamData {
+    TypeParamData(TypeParamData),
+    ConstParamData(ConstParamData),
+    LifetimeParamData(LifetimeParamData),
+}
+
+impl GenericParamData {
+    pub fn name(&self) -> Option<&Name> {
+        match self {
+            GenericParamData::TypeParamData(it) => it.name.as_ref(),
+            GenericParamData::ConstParamData(it) => Some(&it.name),
+            GenericParamData::LifetimeParamData(it) => Some(&it.name),
+        }
+    }
+
+    pub fn type_param(&self) -> Option<&TypeParamData> {
+        match self {
+            GenericParamData::TypeParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn const_param(&self) -> Option<&ConstParamData> {
+        match self {
+            GenericParamData::ConstParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
+        match self {
+            GenericParamData::LifetimeParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+}
+
+impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
+
 /// Data about the generic parameters of a function, struct, impl, etc.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct GenericParams {
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index e311338a2d6..536542f9a07 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -9,8 +9,7 @@ use chalk_ir::{
     AdtId, DebruijnIndex, Scalar,
 };
 use hir_def::{
-    builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
-    GenericDefId, TraitId, TypeAliasId,
+    builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
 };
 use smallvec::SmallVec;
 
@@ -209,10 +208,11 @@ impl TyBuilder<()> {
         Substitution::from_iter(
             Interner,
             params.iter_id().map(|id| match id {
-                either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
-                either::Either::Right(id) => {
+                GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+                GenericParamId::ConstParamId(id) => {
                     unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
                 }
+                GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
             }),
         )
     }
@@ -225,16 +225,13 @@ impl TyBuilder<()> {
     ) -> TyBuilder<()> {
         let generics = generics(db.upcast(), def.into());
         assert!(generics.parent_generics().is_some() == parent_subst.is_some());
-        let lt_iter = generics.iter_lt_self().map(|_| ParamKind::Lifetime);
         let params = generics
             .iter_self()
-            .map(|(id, data)| match data {
-                TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
-                TypeOrConstParamData::ConstParamData(_) => {
-                    ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
-                }
+            .map(|(id, _data)| match id {
+                GenericParamId::TypeParamId(_) => ParamKind::Type,
+                GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
+                GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
             })
-            .chain(lt_iter)
             .collect();
         TyBuilder::new((), params, parent_subst)
     }
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index edfc8a81654..82f7e87ac91 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -8,13 +8,12 @@ use std::{
 use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
 use either::Either;
 use hir_def::{
-    generics::TypeOrConstParamData,
     hir::{
         ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
     },
     lang_item::{LangItem, LangItemTarget},
     path::{GenericArgs, Path},
-    BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+    BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
 };
 use hir_expand::name::{name, Name};
 use stdx::always;
@@ -1836,7 +1835,7 @@ impl InferenceContext<'_> {
                 .args
                 .iter()
                 .take(type_params + const_params + lifetime_params)
-                .zip(def_generics.iter_id_with_lt())
+                .zip(def_generics.iter_id())
             {
                 if let Some(g) = generic_arg_to_chalk(
                     self.db,
@@ -1866,16 +1865,16 @@ impl InferenceContext<'_> {
 
         // Handle everything else as unknown. This also handles generic arguments for the method's
         // parent (impl or trait), which should come after those for the method.
-        for (id, data) in def_generics.iter().skip(substs.len()) {
-            match data {
-                TypeOrConstParamData::TypeParamData(_) => {
+        for (id, _data) in def_generics.iter().skip(substs.len()) {
+            match id {
+                GenericParamId::TypeParamId(_) => {
                     substs.push(self.table.new_type_var().cast(Interner))
                 }
-                TypeOrConstParamData::ConstParamData(_) => substs.push(
-                    self.table
-                        .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
-                        .cast(Interner),
-                ),
+                GenericParamId::ConstParamId(id) => {
+                    substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
+                }
+                // FIXME: create `new_lifetime_var` in infer
+                GenericParamId::LifetimeParamId(_) => substs.push(static_lifetime().cast(Interner)),
             }
         }
         assert_eq!(substs.len(), total_len);
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index f5410ca6a14..fc7ed79f5cf 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -337,7 +337,7 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
     generics: &Generics,
     value: T,
 ) -> Binders<T> {
-    let it = generics.iter_id_with_lt().take(count);
+    let it = generics.iter_id().take(count);
 
     Binders::new(
         VariableKinds::from_iter(
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 453ac2fca78..854893fcee0 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -18,13 +18,13 @@ use chalk_ir::{
     cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety,
 };
 
-use either::Either;
 use hir_def::{
     builtin_type::BuiltinType,
     data::adt::StructKind,
     expander::Expander,
     generics::{
-        TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+        GenericParamData, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+        WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     nameres::MacroSubNs,
@@ -354,13 +354,18 @@ impl<'a> TyLoweringContext<'a> {
                                 .filter(|(_, data)| {
                                     matches!(
                                         data,
-                                        TypeOrConstParamData::TypeParamData(data)
+                                        GenericParamData::TypeParamData(data)
                                         if data.provenance == TypeParamProvenance::ArgumentImplTrait
                                     )
                                 })
                                 .nth(idx as usize)
                                 .map_or(TyKind::Error, |(id, _)| {
-                                    TyKind::Placeholder(to_placeholder_idx(self.db, id))
+                                    if let GenericParamId::TypeParamId(id) = id {
+                                        TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+                                    } else {
+                                        // we just filtered them out
+                                        unreachable!("Unexpected lifetime or const argument");
+                                    }
                                 });
                             param.intern(Interner)
                         } else {
@@ -837,7 +842,7 @@ impl<'a> TyLoweringContext<'a> {
 
         let ty_error = TyKind::Error.intern(Interner).cast(Interner);
 
-        let mut def_generic_iter = def_generics.iter_id_with_lt();
+        let mut def_generic_iter = def_generics.iter_id();
 
         let fill_self_params = || {
             for x in explicit_self_ty
@@ -1732,9 +1737,9 @@ pub(crate) fn generic_defaults_query(
     let generic_params = generics(db.upcast(), def);
     let parent_start_idx = generic_params.len_self();
 
-    let toc_iter = generic_params.iter().enumerate().map(|(idx, (id, p))| {
+    let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
         match p {
-            TypeOrConstParamData::TypeParamData(p) => {
+            GenericParamData::TypeParamData(p) => {
                 let mut ty =
                     p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
                 // Each default can only refer to previous parameters.
@@ -1743,13 +1748,13 @@ pub(crate) fn generic_defaults_query(
                 ty = fallback_bound_vars(ty, idx, parent_start_idx);
                 crate::make_binders(db, &generic_params, ty.cast(Interner))
             }
-            TypeOrConstParamData::ConstParamData(p) => {
+            GenericParamData::ConstParamData(p) => {
+                let GenericParamId::ConstParamId(id) = id else {
+                    unreachable!("Unexpected lifetime or type argument")
+                };
+
                 let mut val = p.default.as_ref().map_or_else(
-                    || {
-                        unknown_const_as_generic(
-                            db.const_param_ty(ConstParamId::from_unchecked(id)),
-                        )
-                    },
+                    || unknown_const_as_generic(db.const_param_ty(id.into())),
                     |c| {
                         let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
                         c.cast(Interner)
@@ -1759,15 +1764,12 @@ pub(crate) fn generic_defaults_query(
                 val = fallback_bound_vars(val, idx, parent_start_idx);
                 make_binders(db, &generic_params, val)
             }
+            GenericParamData::LifetimeParamData(_) => {
+                // using static because it requires defaults
+                make_binders(db, &generic_params, static_lifetime().cast(Interner))
+            }
         }
-    });
-
-    let lt_iter = generic_params
-        .iter_lt()
-        .enumerate()
-        .map(|_| make_binders(db, &generic_params, static_lifetime().cast(Interner)));
-
-    let defaults = Arc::from_iter(toc_iter.chain(lt_iter));
+    }));
 
     defaults
 }
@@ -1782,8 +1784,9 @@ pub(crate) fn generic_defaults_recover(
     // we still need one default per parameter
     let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
         let val = match id {
-            Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
-            Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
+            GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+            GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
+            GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
         };
         crate::make_binders(db, &generic_params, val)
     }));
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index 12ad67cdc45..d6557c3a816 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -184,8 +184,16 @@ impl Filler<'_> {
                                     self.generics
                                         .as_ref()
                                         .and_then(|it| it.iter().nth(b.index))
-                                        .unwrap()
-                                        .0,
+                                        .and_then(|(id, _)| match id {
+                                            hir_def::GenericParamId::ConstParamId(id) => {
+                                                Some(hir_def::TypeOrConstParamId::from(id))
+                                            }
+                                            hir_def::GenericParamId::TypeParamId(id) => {
+                                                Some(hir_def::TypeOrConstParamId::from(id))
+                                            }
+                                            _ => None,
+                                        })
+                                        .unwrap(),
                                     self.subst.clone(),
                                 )
                             })?
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 39e7bdd9623..cadb099c2b8 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -9,12 +9,11 @@ use chalk_ir::{
     fold::{FallibleTypeFolder, Shift},
     BoundVar, DebruijnIndex,
 };
-use either::Either;
 use hir_def::{
     db::DefDatabase,
     generics::{
-        GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
-        WherePredicate, WherePredicateTypeTarget,
+        GenericParamData, GenericParams, LifetimeParamData, TypeOrConstParamData,
+        TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
@@ -271,81 +270,102 @@ pub(crate) struct Generics {
 }
 
 impl Generics {
-    pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
-        self.iter().map(|(id, data)| match data {
-            TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
-            TypeOrConstParamData::ConstParamData(_) => {
-                Either::Right(ConstParamId::from_unchecked(id))
-            }
-        })
+    pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+        self.iter().map(|(id, _)| id)
     }
 
     /// Iterator over types and const params of self, then parent.
     pub(crate) fn iter<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
-        let to_toc_id = |it: &'a Generics| {
-            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamData::TypeParamData(p.clone()),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamData::ConstParamData(p.clone()),
+                    ),
+                }
+            }
         };
-        self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
+
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamData::LifetimeParamData(p.clone()),
+                )
+            }
+        };
+
+        let lt_iter = self.params.iter_lt().map(from_lt_id(self));
+        self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent())
     }
 
     /// Iterate over types and const params without parent params.
     pub(crate) fn iter_self<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
-        let to_toc_id = |it: &'a Generics| {
-            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamData::TypeParamData(p.clone()),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamData::ConstParamData(p.clone()),
+                    ),
+                }
+            }
         };
-        self.params.iter().map(to_toc_id(self))
-    }
 
-    /// Iterator over types and const params of parent.
-    pub(crate) fn iter_parent(
-        &self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
-        self.parent_generics().into_iter().flat_map(|it| {
-            let to_toc_id =
-                move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
-            it.params.iter().map(to_toc_id)
-        })
-    }
-
-    pub(crate) fn iter_id_with_lt(&self) -> impl Iterator<Item = GenericParamId> + '_ {
-        let toc_iter = self.iter().map(|(id, data)| match data {
-            TypeOrConstParamData::TypeParamData(_) => {
-                GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
-            }
-            TypeOrConstParamData::ConstParamData(_) => {
-                GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamData::LifetimeParamData(p.clone()),
+                )
             }
-        });
-        let lt_iter = self.iter_lt().map(|(id, _)| GenericParamId::LifetimeParamId(id));
-
-        toc_iter.chain(lt_iter)
-    }
-
-    pub(crate) fn iter_lt<'a>(
-        &'a self,
-    ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
-        self.iter_lt_self().chain(self.iter_lt_parent())
-    }
-
-    fn iter_lt_self<'a>(
-        &'a self,
-    ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
-        let to_id = |it: &'a Generics| {
-            move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p)
         };
-        self.params.iter_lt().map(to_id(self))
+
+        self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
     }
 
-    fn iter_lt_parent(
+    /// Iterator over types and const params of parent.
+    pub(crate) fn iter_parent(
         &self,
-    ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &LifetimeParamData)> {
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + '_ {
         self.parent_generics().into_iter().flat_map(|it| {
-            let to_id = move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p);
-            it.params.iter_lt().map(to_id)
+            let from_toc_id = move |(local_id, p): (_, &TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamData::TypeParamData(p.clone()),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamData::ConstParamData(p.clone()),
+                    ),
+                }
+            };
+
+            let from_lt_id = move |(local_id, p): (_, &LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamData::LifetimeParamData(p.clone()),
+                )
+            };
+            let lt_iter = it.params.iter_lt().map(from_lt_id);
+            it.params.iter().map(from_toc_id).chain(lt_iter)
         })
     }
 
@@ -437,7 +457,7 @@ impl Generics {
     ) -> Substitution {
         Substitution::from_iter(
             Interner,
-            self.iter_id_with_lt().enumerate().map(|(idx, id)| match id {
+            self.iter_id().enumerate().map(|(idx, id)| match id {
                 GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
@@ -456,12 +476,15 @@ impl Generics {
         Substitution::from_iter(
             Interner,
             self.iter_id().map(|id| match id {
-                Either::Left(id) => {
+                GenericParamId::TypeParamId(id) => {
                     crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
                 }
-                Either::Right(id) => crate::to_placeholder_idx(db, id.into())
-                    .to_const(Interner, db.const_param_ty(id))
+                GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
+                    .to_const(Interner, db.const_param_ty(id.into()))
                     .cast(Interner),
+                GenericParamId::LifetimeParamId(id) => {
+                    crate::lt_to_placeholder_idx(db, id.into()).to_lifetime(Interner).cast(Interner)
+                }
             }),
         )
     }