From f95b3d4cd206f9ffc5a7a937e66afb6dacb75867 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 6 Mar 2024 16:39:24 +0530 Subject: [PATCH 01/12] implement resolving and lowering of Lifetimes --- crates/hir-def/src/generics.rs | 25 +++++++++++++++-- crates/hir-def/src/resolver.rs | 25 +++++++++++++++++ crates/hir-ty/src/lower.rs | 50 +++++++++++++++++++++++++++------- crates/hir-ty/src/mapping.rs | 8 ++++++ crates/hir-ty/src/utils.rs | 34 ++++++++++++++++++++--- 5 files changed, 126 insertions(+), 16 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 1d2c7c3a55f..8bdd9c6587d 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -22,8 +22,8 @@ use crate::{ lower::LowerCtx, nameres::{DefMap, MacroSubNs}, type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef}, - AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup, - TypeOrConstParamId, TypeParamId, + AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId, + LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, }; /// Data about a generic type parameter (to a function, struct, impl, ...). @@ -365,6 +365,13 @@ impl GenericParams { self.type_or_consts.iter() } + /// Iterator of lifetimes field + pub fn iter_lt( + &self, + ) -> impl DoubleEndedIterator, &LifetimeParamData)> { + self.lifetimes.iter() + } + pub(crate) fn generic_params_query( db: &dyn DefDatabase, def: GenericDefId, @@ -507,4 +514,18 @@ impl GenericParams { .then(|| id) }) } + + pub fn find_lifetime_by_name( + &self, + name: &Name, + parent: GenericDefId, + ) -> Option { + self.lifetimes.iter().find_map(|(id, p)| { + if &p.name == name { + Some(LifetimeParamId { local_id: id, parent }) + } else { + None + } + }) + } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 226d6f513f5..bfad75c50b6 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -24,6 +24,7 @@ use crate::{ nameres::{DefMap, MacroSubNs}, path::{ModPath, Path, PathKind}, per_ns::PerNs, + type_ref::LifetimeRef, visibility::{RawVisibility, Visibility}, AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, @@ -120,6 +121,12 @@ pub enum ValueNs { GenericParam(ConstParamId), } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum LifetimeNs { + Static, + LifetimeParam(LifetimeParamId), +} + impl Resolver { /// Resolve known trait from std, like `std::futures::Future` pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option { @@ -418,6 +425,24 @@ impl Resolver { self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it)) } + pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option { + if lifetime.name == name::known::STATIC_LIFETIME { + return Some(LifetimeNs::Static); + } + + for scope in self.scopes() { + match scope { + Scope::GenericParams { def, params } => { + if let Some(id) = params.find_lifetime_by_name(&lifetime.name, *def) { + return Some(LifetimeNs::LifetimeParam(id)); + } + } + _ => continue, + } + } + None + } + /// Returns a set of names available in the current scope. /// /// Note that this is a somewhat fuzzy concept -- internally, the compiler diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 0bc739e6963..af1a91a06a6 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -29,8 +29,10 @@ use hir_def::{ lang_item::LangItem, nameres::MacroSubNs, path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments}, - resolver::{HasResolver, Resolver, TypeNs}, - type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef}, + resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, + type_ref::{ + ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, + }, AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, @@ -53,17 +55,17 @@ use crate::{ }, db::HirDatabase, make_binders, - mapping::{from_chalk_trait_id, ToChalk}, + mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, - utils::Generics, utils::{ - all_super_trait_refs, associated_type_by_name_including_super_traits, generics, + all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, InTypeConstIdMetadata, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, - FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind, - PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, - TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, + FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, + LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause, + QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, + TyKind, WhereClause, }; #[derive(Debug)] @@ -275,9 +277,10 @@ impl<'a> TyLoweringContext<'a> { let inner_ty = self.lower_ty(inner); TyKind::Slice(inner_ty).intern(Interner) } - TypeRef::Reference(inner, _, mutability) => { + TypeRef::Reference(inner, lifetime, mutability) => { let inner_ty = self.lower_ty(inner); - let lifetime = static_lifetime(); + let lifetime = + lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr)); TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty) .intern(Interner) } @@ -1309,6 +1312,33 @@ impl<'a> TyLoweringContext<'a> { }); ImplTrait { bounds: crate::make_single_type_binders(predicates) } } + + fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime { + match self.resolver.resolve_lifetime(lifetime) { + Some(resolution) => match resolution { + LifetimeNs::Static => static_lifetime(), + LifetimeNs::LifetimeParam(id) => match self.type_param_mode { + ParamLoweringMode::Placeholder => { + LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id)) + } + ParamLoweringMode::Variable => { + let generics = generics( + self.db.upcast(), + self.resolver.generic_def().expect("generics in scope"), + ); + let idx = match generics.lifetime_idx(id) { + None => return static_lifetime(), + Some(idx) => idx, + }; + + LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx)) + } + } + .intern(Interner), + }, + None => static_lifetime(), + } + } } fn count_impl_traits(type_ref: &TypeRef) -> usize { diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs index fba760974f2..14746260396 100644 --- a/crates/hir-ty/src/mapping.rs +++ b/crates/hir-ty/src/mapping.rs @@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L db.lookup_intern_lifetime_param_id(interned_id) } +pub(crate) fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex { + let interned_id = db.intern_lifetime_param_id(id); + PlaceholderIndex { + ui: chalk_ir::UniverseIndex::ROOT, + idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), + } +} + pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) } diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 8bd57820d2c..84fcc31dd4b 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -13,14 +13,15 @@ use either::Either; use hir_def::{ db::DefDatabase, generics::{ - GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate, - WherePredicateTypeTarget, + GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance, + WherePredicate, WherePredicateTypeTarget, }, lang_item::LangItem, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, - ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup, - OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, + ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, + LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, + TypeParamId, }; use hir_expand::name::Name; use intern::Interned; @@ -322,6 +323,11 @@ impl Generics { self.params.type_or_consts.len() } + /// Returns number of generic lifetime excluding those from parent. + pub(crate) fn len_lt_self(&self) -> usize { + self.params.lifetimes.len() + } + /// (parent total, self param, type param list, const param list, impl trait) pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) { let mut self_params = 0; @@ -358,6 +364,26 @@ impl Generics { } } + pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option { + Some(self.find_lifetime(lifetime)?.0) + } + + fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> { + if lifetime.parent == self.def { + let (idx, (_local_id, data)) = self + .params + .iter_lt() + .enumerate() + .find(|(_, (idx, _))| *idx == lifetime.local_id)?; + + Some((idx, data)) + } else { + self.parent_generics() + .and_then(|g| g.find_lifetime(lifetime)) + .map(|(idx, data)| (self.len_lt_self() + idx, data)) + } + } + pub(crate) fn parent_generics(&self) -> Option<&Generics> { self.parent_generics.as_deref() } From 16493e301ee6eca66ce8806c2e92139e7a964193 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 6 Mar 2024 23:15:04 +0530 Subject: [PATCH 02/12] fix index returned for the use of BoundVar --- crates/hir-ty/src/lib.rs | 4 ++++ crates/hir-ty/src/lower.rs | 6 +++--- crates/hir-ty/src/utils.rs | 14 +++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index d6d5c16ae75..accf306dde0 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -611,6 +611,10 @@ pub fn static_lifetime() -> Lifetime { LifetimeData::Static.intern(Interner) } +pub fn error_lifetime() -> Lifetime { + static_lifetime() +} + pub(crate) fn fold_free_vars + TypeFoldable>( t: T, for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index af1a91a06a6..3327d284799 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -54,7 +54,7 @@ use crate::{ unknown_const_as_generic, }, db::HirDatabase, - make_binders, + error_lifetime, make_binders, mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::{ @@ -1327,7 +1327,7 @@ impl<'a> TyLoweringContext<'a> { self.resolver.generic_def().expect("generics in scope"), ); let idx = match generics.lifetime_idx(id) { - None => return static_lifetime(), + None => return error_lifetime(), Some(idx) => idx, }; @@ -1336,7 +1336,7 @@ impl<'a> TyLoweringContext<'a> { } .intern(Interner), }, - None => static_lifetime(), + None => error_lifetime(), } } } diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 84fcc31dd4b..f45fe863df1 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -318,14 +318,14 @@ impl Generics { parent + child } - /// Returns numbers of generic parameters excluding those from parent. + /// Returns numbers of generic parameters and lifetimes excluding those from parent. pub(crate) fn len_self(&self) -> usize { - self.params.type_or_consts.len() + self.params.type_or_consts.len() + self.params.lifetimes.len() } - /// Returns number of generic lifetime excluding those from parent. - pub(crate) fn len_lt_self(&self) -> usize { - self.params.lifetimes.len() + /// Returns number of generic parameter excluding those from parent + fn len_params(&self) -> usize { + self.params.type_or_consts.len() } /// (parent total, self param, type param list, const param list, impl trait) @@ -376,11 +376,11 @@ impl Generics { .enumerate() .find(|(_, (idx, _))| *idx == lifetime.local_id)?; - Some((idx, data)) + Some((self.len_params() + idx, data)) } else { self.parent_generics() .and_then(|g| g.find_lifetime(lifetime)) - .map(|(idx, data)| (self.len_lt_self() + idx, data)) + .map(|(idx, data)| (self.len_self() + idx, data)) } } From e463a3e1cf5041581bdc8ede2488d60a1ef638ae Mon Sep 17 00:00:00 2001 From: dfireBird Date: Fri, 8 Mar 2024 18:00:07 +0530 Subject: [PATCH 03/12] update `make_binders` to include lifetimes in generics adds a bunch of iter methods that include lifetimes --- crates/hir-ty/src/lib.rs | 22 ++++++++++++---- crates/hir-ty/src/utils.rs | 53 ++++++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index accf306dde0..97a8f8660a4 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -337,11 +337,23 @@ pub(crate) fn make_binders_with_count>( generics: &Generics, value: T, ) -> Binders { - let it = generics.iter_id().take(count).map(|id| match id { - Either::Left(_) => None, - Either::Right(id) => Some(db.const_param_ty(id)), - }); - crate::make_type_and_const_binders(it, value) + let it = generics.iter_id_with_lt().take(count); + + Binders::new( + VariableKinds::from_iter( + Interner, + it.map(|x| match x { + hir_def::GenericParamId::ConstParamId(id) => { + chalk_ir::VariableKind::Const(db.const_param_ty(id)) + } + hir_def::GenericParamId::TypeParamId(_) => { + chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General) + } + hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime, + }), + ), + value, + ) } pub(crate) fn make_binders>( diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index f45fe863df1..5e084ffb08b 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -19,7 +19,7 @@ use hir_def::{ lang_item::LangItem, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, - ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, + ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, }; @@ -311,10 +311,48 @@ impl Generics { }) } + pub(crate) fn iter_id_with_lt(&self) -> impl Iterator + '_ { + 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 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 + 'a { + self.iter_lt_self().chain(self.iter_lt_parent()) + } + + fn iter_lt_self<'a>( + &'a self, + ) -> impl DoubleEndedIterator + '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)) + } + + fn iter_lt_parent( + &self, + ) -> impl DoubleEndedIterator { + 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) + }) + } + /// Returns total number of generic parameters in scope, including those from parent. pub(crate) fn len(&self) -> usize { let parent = self.parent_generics().map_or(0, Generics::len); - let child = self.params.type_or_consts.len(); + let child = self.params.type_or_consts.len() + self.params.lifetimes.len(); parent + child } @@ -396,11 +434,16 @@ impl Generics { ) -> Substitution { Substitution::from_iter( Interner, - self.iter_id().enumerate().map(|(idx, id)| match id { - Either::Left(_) => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner), - Either::Right(id) => BoundVar::new(debruijn, idx) + self.iter_id_with_lt().enumerate().map(|(idx, id)| match id { + GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx) .to_const(Interner, db.const_param_ty(id)) .cast(Interner), + GenericParamId::TypeParamId(_) => { + BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner) + } + GenericParamId::LifetimeParamId(_) => { + BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner) + } }), ) } From d6e3929841cbf78adff4e2edb0f6005919ad3a35 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Fri, 8 Mar 2024 18:05:44 +0530 Subject: [PATCH 04/12] include lifetime in ParamKind and in Generics::provenance_split --- crates/hir-ty/src/builder.rs | 20 ++++++-- crates/hir-ty/src/display.rs | 16 +++++-- crates/hir-ty/src/infer/expr.rs | 22 ++++++--- crates/hir-ty/src/infer/path.rs | 3 +- crates/hir-ty/src/infer/unify.rs | 1 + crates/hir-ty/src/lib.rs | 4 +- crates/hir-ty/src/lower.rs | 82 +++++++++++++++++++++----------- crates/hir-ty/src/mapping.rs | 2 +- crates/hir-ty/src/utils.rs | 7 ++- crates/hir/src/lib.rs | 9 +++- 10 files changed, 116 insertions(+), 50 deletions(-) diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index c485c9b2e80..e311338a2d6 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -15,15 +15,16 @@ use hir_def::{ use smallvec::SmallVec; use crate::{ - consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive, - to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig, - GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, - TyKind, + consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, + infer::unify::InferenceTable, primitive, static_lifetime, to_assoc_type_id, to_chalk_trait_id, + utils::generics, Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, + ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind, }; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ParamKind { Type, + Lifetime, Const(Ty), } @@ -107,6 +108,9 @@ impl TyBuilder { ParamKind::Const(ty) => { BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner) } + ParamKind::Lifetime => { + BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner) + } }); this.vec.extend(filler.take(this.remaining()).casted(Interner)); assert_eq!(this.remaining(), 0); @@ -119,6 +123,7 @@ impl TyBuilder { let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x { ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }); this.vec.extend(filler.casted(Interner)); assert_eq!(this.remaining(), 0); @@ -130,6 +135,8 @@ impl TyBuilder { self.fill(|x| match x { ParamKind::Type => table.new_type_var().cast(Interner), ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner), + // FIXME: create new_lifetime_var in table + ParamKind::Lifetime => static_lifetime().cast(Interner), }) } @@ -142,7 +149,8 @@ impl TyBuilder { fn assert_match_kind(&self, a: &chalk_ir::GenericArg, e: &ParamKind) { match (a.data(Interner), e) { (GenericArgData::Ty(_), ParamKind::Type) - | (GenericArgData::Const(_), ParamKind::Const(_)) => (), + | (GenericArgData::Const(_), ParamKind::Const(_)) + | (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (), _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds), } } @@ -217,6 +225,7 @@ 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 { @@ -225,6 +234,7 @@ impl TyBuilder<()> { ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id))) } }) + .chain(lt_iter) .collect(); TyBuilder::new((), params, parent_subst) } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 269db57bc34..32be0f248bf 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -938,15 +938,23 @@ impl HirDisplay for Ty { f.end_location_link(); if parameters.len(Interner) > 0 { let generics = generics(db.upcast(), def.into()); - let (parent_params, self_param, type_params, const_params, _impl_trait_params) = - generics.provenance_split(); - let total_len = parent_params + self_param + type_params + const_params; + let ( + parent_params, + self_param, + type_params, + const_params, + _impl_trait_params, + lifetime_params, + ) = generics.provenance_split(); + let total_len = + parent_params + self_param + type_params + const_params + lifetime_params; // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? if total_len > 0 { // `parameters` are in the order of fn's params (including impl traits), // parent's params (those from enclosing impl or trait, if any). let parameters = parameters.as_slice(Interner); - let fn_params_len = self_param + type_params + const_params; + let fn_params_len = + self_param + type_params + const_params + lifetime_params; let fn_params = parameters.get(..fn_params_len); let parent_params = parameters.get(parameters.len() - parent_params..); let params = parent_params.into_iter().chain(fn_params).flatten(); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index a3dab1fd9d5..edfc8a81654 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -13,7 +13,7 @@ use hir_def::{ ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp, }, lang_item::{LangItem, LangItemTarget}, - path::{GenericArg, GenericArgs, Path}, + path::{GenericArgs, Path}, BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId, }; use hir_expand::name::{name, Name}; @@ -1816,10 +1816,17 @@ impl InferenceContext<'_> { def_generics: Generics, generic_args: Option<&GenericArgs>, ) -> Substitution { - let (parent_params, self_params, type_params, const_params, impl_trait_params) = - def_generics.provenance_split(); + let ( + parent_params, + self_params, + type_params, + const_params, + impl_trait_params, + lifetime_params, + ) = def_generics.provenance_split(); assert_eq!(self_params, 0); // method shouldn't have another Self param - let total_len = parent_params + type_params + const_params + impl_trait_params; + let total_len = + parent_params + type_params + const_params + impl_trait_params + lifetime_params; let mut substs = Vec::with_capacity(total_len); // handle provided arguments @@ -1828,9 +1835,8 @@ impl InferenceContext<'_> { for (arg, kind_id) in generic_args .args .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) - .take(type_params + const_params) - .zip(def_generics.iter_id()) + .take(type_params + const_params + lifetime_params) + .zip(def_generics.iter_id_with_lt()) { if let Some(g) = generic_arg_to_chalk( self.db, @@ -1850,6 +1856,8 @@ impl InferenceContext<'_> { DebruijnIndex::INNERMOST, ) }, + // FIXME: create make_lifetimes and infer lifetimes + |_, _| static_lifetime(), ) { substs.push(g); } diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 44b35b2ebbc..9a1835b625b 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -11,7 +11,7 @@ use stdx::never; use crate::{ builder::ParamKind, - consteval, + consteval, error_lifetime, method_resolution::{self, VisibleFromModule}, to_chalk_trait_id, utils::generics, @@ -111,6 +111,7 @@ impl InferenceContext<'_> { it.next().unwrap_or_else(|| match x { ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner), ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }) }) .build(); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 93fd54455b9..a6c5666911a 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -807,6 +807,7 @@ impl<'a> InferenceTable<'a> { .fill(|it| { let arg = match it { ParamKind::Type => self.new_type_var(), + ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"), ParamKind::Const(_) => unreachable!("Tuple with const parameter"), }; arg_tys.push(arg.clone()); diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 97a8f8660a4..f5410ca6a14 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -92,8 +92,8 @@ pub use lower::{ }; pub use mapping::{ from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, - lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, - to_placeholder_idx, + lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, + to_foreign_def_id, to_placeholder_idx, }; pub use method_resolution::check_orphan_rules; pub use traits::TraitEnvironment; diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 3327d284799..453ac2fca78 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -34,9 +34,9 @@ use hir_def::{ ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, }, AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup, - ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, - TypeParamId, UnionId, VariantId, + GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, + Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, + UnionId, VariantId, }; use hir_expand::{name::Name, ExpandResult}; use intern::Interned; @@ -377,15 +377,20 @@ impl<'a> TyLoweringContext<'a> { list_params, const_params, _impl_trait_params, + lifetime_params, ) = if let Some(def) = self.resolver.generic_def() { let generics = generics(self.db.upcast(), def); generics.provenance_split() } else { - (0, 0, 0, 0, 0) + (0, 0, 0, 0, 0, 0) }; TyKind::BoundVar(BoundVar::new( self.in_binders, - idx as usize + self_params + list_params + const_params, + idx as usize + + self_params + + list_params + + const_params + + lifetime_params, )) .intern(Interner) } @@ -818,14 +823,21 @@ impl<'a> TyLoweringContext<'a> { return Substitution::empty(Interner); }; let def_generics = generics(self.db.upcast(), def); - let (parent_params, self_params, type_params, const_params, impl_trait_params) = - def_generics.provenance_split(); - let item_len = self_params + type_params + const_params + impl_trait_params; + let ( + parent_params, + self_params, + type_params, + const_params, + impl_trait_params, + lifetime_params, + ) = def_generics.provenance_split(); + let item_len = + self_params + type_params + const_params + impl_trait_params + lifetime_params; let total_len = parent_params + item_len; let ty_error = TyKind::Error.intern(Interner).cast(Interner); - let mut def_generic_iter = def_generics.iter_id(); + let mut def_generic_iter = def_generics.iter_id_with_lt(); let fill_self_params = || { for x in explicit_self_ty @@ -835,7 +847,10 @@ impl<'a> TyLoweringContext<'a> { .take(self_params) { if let Some(id) = def_generic_iter.next() { - assert!(id.is_left()); + assert!(matches!( + id, + GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_) + )); substs.push(x); } } @@ -847,19 +862,13 @@ impl<'a> TyLoweringContext<'a> { fill_self_params(); } let expected_num = if generic_args.has_self_type { - self_params + type_params + const_params + self_params + type_params + const_params + lifetime_params } else { type_params + const_params }; let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; // if args are provided, it should be all of them, but we can't rely on that - for arg in generic_args - .args - .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) - .skip(skip) - .take(expected_num) - { + for arg in generic_args.args.iter().skip(skip).take(expected_num) { if let Some(id) = def_generic_iter.next() { if let Some(x) = generic_arg_to_chalk( self.db, @@ -868,6 +877,7 @@ impl<'a> TyLoweringContext<'a> { &mut (), |_, type_ref| self.lower_ty(type_ref), |_, const_ref, ty| self.lower_const(const_ref, ty), + |_, lifetime_ref| self.lower_lifetime(lifetime_ref), ) { had_explicit_args = true; substs.push(x); @@ -883,9 +893,12 @@ impl<'a> TyLoweringContext<'a> { // These params include those of parent. let remaining_params: SmallVec<[_; 2]> = def_generic_iter - .map(|eid| match eid { - Either::Left(_) => ty_error.clone(), - Either::Right(x) => unknown_const_as_generic(self.db.const_param_ty(x)), + .map(|id| match id { + GenericParamId::ConstParamId(x) => { + unknown_const_as_generic(self.db.const_param_ty(x)) + } + GenericParamId::TypeParamId(_) => ty_error.clone(), + GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), }) .collect(); assert_eq!(remaining_params.len() + substs.len(), total_len); @@ -1719,7 +1732,7 @@ pub(crate) fn generic_defaults_query( let generic_params = generics(db.upcast(), def); let parent_start_idx = generic_params.len_self(); - let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| { + let toc_iter = generic_params.iter().enumerate().map(|(idx, (id, p))| { match p { TypeOrConstParamData::TypeParamData(p) => { let mut ty = @@ -1747,7 +1760,14 @@ pub(crate) fn generic_defaults_query( make_binders(db, &generic_params, val) } } - })); + }); + + 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 } @@ -2127,23 +2147,29 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut /// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime. pub(crate) fn generic_arg_to_chalk<'a, T>( db: &dyn HirDatabase, - kind_id: Either, + kind_id: GenericParamId, arg: &'a GenericArg, this: &mut T, for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a, for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a, + for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a, ) -> Option { let kind = match kind_id { - Either::Left(_) => ParamKind::Type, - Either::Right(id) => { + GenericParamId::TypeParamId(_) => ParamKind::Type, + GenericParamId::ConstParamId(id) => { let ty = db.const_param_ty(id); ParamKind::Const(ty) } + GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime, }; Some(match (arg, kind) { (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner), (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner), + (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => { + for_lifetime(this, lifetime_ref).cast(Interner) + } (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner), + (GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner), (GenericArg::Type(t), ParamKind::Const(c_ty)) => { // We want to recover simple idents, which parser detects them // as types. Maybe here is not the best place to do it, but @@ -2159,7 +2185,9 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( } unknown_const_as_generic(c_ty) } - (GenericArg::Lifetime(_), _) => return None, + (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty), + (GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner), + (GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner), }) } diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs index 14746260396..c61d8277142 100644 --- a/crates/hir-ty/src/mapping.rs +++ b/crates/hir-ty/src/mapping.rs @@ -151,7 +151,7 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L db.lookup_intern_lifetime_param_id(interned_id) } -pub(crate) fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex { +pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex { let interned_id = db.intern_lifetime_param_id(id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 5e084ffb08b..39e7bdd9623 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -367,11 +367,12 @@ impl Generics { } /// (parent total, self param, type param list, const param list, impl trait) - pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) { + pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) { let mut self_params = 0; let mut type_params = 0; let mut impl_trait_params = 0; let mut const_params = 0; + let mut lifetime_params = 0; self.params.iter().for_each(|(_, data)| match data { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::TypeParamList => type_params += 1, @@ -381,8 +382,10 @@ impl Generics { TypeOrConstParamData::ConstParamData(_) => const_params += 1, }); + self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1); + let parent_len = self.parent_generics().map_or(0, Generics::len); - (parent_len, self_params, type_params, const_params, impl_trait_params) + (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params) } pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4f9697f7fe4..f3065fab826 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -65,7 +65,7 @@ use hir_ty::{ consteval::{try_const_usize, unknown_const_as_generic, ConstExt}, db::InternedClosure, diagnostics::BodyValidationDiagnostic, - known_const_to_ast, + error_lifetime, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, mir::{interpret_mir, MutBorrowKind}, @@ -1106,6 +1106,7 @@ impl Field { generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) } ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }) .build(); let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); @@ -1447,6 +1448,7 @@ impl Adt { match x { ParamKind::Type => r.cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), } }) .build(); @@ -1865,6 +1867,7 @@ impl Function { generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) } ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }; let parent_substs = @@ -1963,6 +1966,7 @@ impl Function { .unwrap_or_else(|| TyKind::Error.intern(Interner)) .cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }) .build() }); @@ -2221,6 +2225,7 @@ impl SelfParam { generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) } ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), }; let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build(); @@ -4114,6 +4119,7 @@ impl Type { // FIXME: this code is not covered in tests. unknown_const_as_generic(ty.clone()) } + ParamKind::Lifetime => error_lifetime().cast(Interner), } }) .build(); @@ -4144,6 +4150,7 @@ impl Type { match it { ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner), ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + ParamKind::Lifetime => error_lifetime().cast(Interner), } }) .build(); From a6c8cbfd9116226541e91528e6a20c26d52ead46 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Sat, 9 Mar 2024 01:08:35 +0530 Subject: [PATCH 05/12] update `Generics` iter methods to return `GenericParamId` --- crates/hir-def/src/generics.rs | 40 ++++++ crates/hir-ty/src/builder.rs | 19 ++- crates/hir-ty/src/infer/expr.rs | 21 ++- crates/hir-ty/src/lib.rs | 2 +- crates/hir-ty/src/lower.rs | 49 +++---- crates/hir-ty/src/mir/monomorphization.rs | 12 +- crates/hir-ty/src/utils.rs | 149 +++++++++++++--------- 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>( generics: &Generics, value: T, ) -> Binders { - 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> + '_ { - 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 + '_ { + self.iter().map(|(id, _)| id) } /// Iterator over types and const params of self, then parent. pub(crate) fn iter<'a>( &'a self, - ) -> impl DoubleEndedIterator + 'a { - let to_toc_id = |it: &'a Generics| { - move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p) + ) -> impl DoubleEndedIterator + '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 + 'a { - let to_toc_id = |it: &'a Generics| { - move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p) + ) -> impl DoubleEndedIterator + '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)) + + let from_lt_id = |it: &'a Generics| { + move |(local_id, p): (_, &LifetimeParamData)| { + ( + GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }), + GenericParamData::LifetimeParamData(p.clone()), + ) + } + }; + + self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self))) } /// Iterator over types and const params of parent. pub(crate) fn iter_parent( &self, - ) -> impl DoubleEndedIterator { + ) -> impl DoubleEndedIterator + '_ { 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) - }) - } + 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()), + ), + } + }; - pub(crate) fn iter_id_with_lt(&self) -> impl Iterator + '_ { - 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 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 + 'a { - self.iter_lt_self().chain(self.iter_lt_parent()) - } - - fn iter_lt_self<'a>( - &'a self, - ) -> impl DoubleEndedIterator + '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)) - } - - fn iter_lt_parent( - &self, - ) -> impl DoubleEndedIterator { - 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_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) + } }), ) } From 0669ae7fafea27f63f4ed36fb788345d9b6128d4 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 11 Mar 2024 02:06:47 +0530 Subject: [PATCH 06/12] handle lifetimes separately in substs function --- crates/hir-ty/src/lower.rs | 46 +++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 854893fcee0..a930708b250 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -382,7 +382,7 @@ impl<'a> TyLoweringContext<'a> { list_params, const_params, _impl_trait_params, - lifetime_params, + _lifetime_params, ) = if let Some(def) = self.resolver.generic_def() { let generics = generics(self.db.upcast(), def); generics.provenance_split() @@ -391,11 +391,7 @@ impl<'a> TyLoweringContext<'a> { }; TyKind::BoundVar(BoundVar::new( self.in_binders, - idx as usize - + self_params - + list_params - + const_params - + lifetime_params, + idx as usize + self_params + list_params + const_params, )) .intern(Interner) } @@ -869,11 +865,17 @@ impl<'a> TyLoweringContext<'a> { let expected_num = if generic_args.has_self_type { self_params + type_params + const_params + lifetime_params } else { - type_params + const_params + type_params + const_params + lifetime_params }; let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; // if args are provided, it should be all of them, but we can't rely on that - for arg in generic_args.args.iter().skip(skip).take(expected_num) { + for arg in generic_args + .args + .iter() + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .skip(skip) + .take(expected_num) + { if let Some(id) = def_generic_iter.next() { if let Some(x) = generic_arg_to_chalk( self.db, @@ -892,6 +894,34 @@ impl<'a> TyLoweringContext<'a> { } } } + + for arg in generic_args + .args + .iter() + .filter(|arg| matches!(arg, GenericArg::Lifetime(_))) + .skip(skip) + .take(expected_num) + { + // Taking into the fact that def_generic_iter will always have lifetimes at the end + // Should have some test cases tho to test this behaviour more properly + if let Some(id) = def_generic_iter.next() { + if let Some(x) = generic_arg_to_chalk( + self.db, + id, + arg, + &mut (), + |_, type_ref| self.lower_ty(type_ref), + |_, const_ref, ty| self.lower_const(const_ref, ty), + |_, lifetime_ref| self.lower_lifetime(lifetime_ref), + ) { + had_explicit_args = true; + substs.push(dbg!(x)); + } else { + // Never return a None explictly + never!("Unexpectd None by generic_arg_to_chalk"); + } + } + } } else { fill_self_params(); } From 490391f576f2d2660537ba0d801f708fd99745cb Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 11 Mar 2024 10:03:40 +0530 Subject: [PATCH 07/12] fix HirDisplay inserting anonymous lifetimes and update tests --- crates/hir-ty/src/display.rs | 17 +++++++---------- crates/hir-ty/src/lower.rs | 6 +++--- crates/hir-ty/src/tests/display_source_code.rs | 2 +- crates/hir-ty/src/tests/patterns.rs | 2 +- crates/hir-ty/src/tests/regression.rs | 4 ++-- crates/hir-ty/src/tests/simple.rs | 6 +++--- .../src/handlers/extract_function.rs | 2 +- .../src/handlers/generate_delegate_methods.rs | 2 +- crates/ide-completion/src/tests/predicate.rs | 4 ++-- crates/ide-completion/src/tests/type_pos.rs | 8 ++++---- 10 files changed, 25 insertions(+), 28 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 32be0f248bf..bc5bd791696 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -1316,8 +1316,7 @@ fn hir_fmt_generics( generic_def: Option, ) -> Result<(), HirDisplayError> { let db = f.db; - let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len()); - if parameters.len(Interner) + lifetime_args_count > 0 { + if parameters.len(Interner) > 0 { let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() { match generic_def .map(|generic_def_id| db.generic_defaults(generic_def_id)) @@ -1343,6 +1342,11 @@ fn hir_fmt_generics( return true; } } + if parameter.lifetime(Interner).map(|it| it.data(Interner)) + == Some(&crate::LifetimeData::Static) + { + return true; + } let default_parameter = match default_parameters.get(i) { Some(it) => it, None => return true, @@ -1363,16 +1367,9 @@ fn hir_fmt_generics( } else { parameters.as_slice(Interner) }; - if !parameters_to_write.is_empty() || lifetime_args_count != 0 { + if !parameters_to_write.is_empty() { write!(f, "<")?; let mut first = true; - for _ in 0..lifetime_args_count { - if !first { - write!(f, ", ")?; - } - first = false; - write!(f, "'_")?; - } for generic_arg in parameters_to_write { if !first { write!(f, ", ")?; diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index a930708b250..9370a2cee04 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -915,10 +915,10 @@ impl<'a> TyLoweringContext<'a> { |_, lifetime_ref| self.lower_lifetime(lifetime_ref), ) { had_explicit_args = true; - substs.push(dbg!(x)); + substs.push(x); } else { - // Never return a None explictly - never!("Unexpectd None by generic_arg_to_chalk"); + // Never return a None explicitly + never!("Unexpected None by generic_arg_to_chalk"); } } } diff --git a/crates/hir-ty/src/tests/display_source_code.rs b/crates/hir-ty/src/tests/display_source_code.rs index e75b037e38d..50692674996 100644 --- a/crates/hir-ty/src/tests/display_source_code.rs +++ b/crates/hir-ty/src/tests/display_source_code.rs @@ -85,7 +85,7 @@ fn render_dyn_for_ty() { trait Foo<'a> {} fn foo(foo: &dyn for<'a> Foo<'a>) {} - // ^^^ &dyn Foo + // ^^^ &dyn Foo<'static> "#, ); } diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 963b4a2aba0..80d5a0ae001 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -1109,7 +1109,7 @@ fn var_args() { #[lang = "va_list"] pub struct VaListImpl<'f>; fn my_fn(foo: ...) {} - //^^^ VaListImpl<'_> + //^^^ VaListImpl<'static> "#, ); } diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 9a8ebd07d01..af016db4dc5 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -896,13 +896,13 @@ fn flush(&self) { "#, expect![[r#" 123..127 'self': &Mutex - 150..152 '{}': MutexGuard<'_, T> + 150..152 '{}': MutexGuard 234..238 'self': &{unknown} 240..290 '{ ...()); }': () 250..251 'w': &Mutex 276..287 '*(w.lock())': BufWriter 278..279 'w': &Mutex - 278..286 'w.lock()': MutexGuard<'_, BufWriter> + 278..286 'w.lock()': MutexGuard "#]], ); } diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 917e9f44085..f39404593e5 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -3092,7 +3092,7 @@ fn main() { 389..394 'boxed': Box> 389..406 'boxed....nner()': &i32 416..421 'good1': &i32 - 424..438 'Foo::get_inner': fn get_inner(&Box>) -> &i32 + 424..438 'Foo::get_inner': fn get_inner(&Box>) -> &i32 424..446 'Foo::g...boxed)': &i32 439..445 '&boxed': &Box> 440..445 'boxed': Box> @@ -3100,7 +3100,7 @@ fn main() { 464..469 'boxed': Box> 464..480 'boxed....self()': &Foo 490..495 'good2': &Foo - 498..511 'Foo::get_self': fn get_self(&Box>) -> &Foo + 498..511 'Foo::get_self': fn get_self(&Box>) -> &Foo 498..519 'Foo::g...boxed)': &Foo 512..518 '&boxed': &Box> 513..518 'boxed': Box> @@ -3659,7 +3659,7 @@ fn main() { let are = "are"; let count = 10; builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!"); - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'_> + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'static> } "#, ); diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index d111005c2ec..981eb18b58f 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -5617,7 +5617,7 @@ fn func(i: Struct<'_, T>) { fun_name(i); } -fn $0fun_name(i: Struct<'_, T>) { +fn $0fun_name(i: Struct) { foo(i); } "#, diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 38f40b8d58b..78d3fa11672 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -614,7 +614,7 @@ struct Foo<'a, T> { } impl<'a, T> Foo<'a, T> { - $0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> { + $0fn bar(self, mut b: Vec<&'a Bar>) -> &'a Bar { self.field.bar(b) } } diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs index 46a3e97d3e9..e7f3eeaecbc 100644 --- a/crates/ide-completion/src/tests/predicate.rs +++ b/crates/ide-completion/src/tests/predicate.rs @@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {} en Enum Enum ma makro!(…) macro_rules! makro md module - st Foo<…> Foo<'_, {unknown}, _> + st Foo<…> Foo<{unknown}, _, 'static> st Record Record st Tuple Tuple st Unit Unit @@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {} en Enum Enum ma makro!(…) macro_rules! makro md module - st Foo<…> Foo<'_, {unknown}, _> + st Foo<…> Foo<{unknown}, _, 'static> st Record Record st Tuple Tuple st Unit Unit diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index db4ac9381ce..60ee7bf4e67 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> { en Enum Enum ma makro!(…) macro_rules! makro md module - sp Self Foo<'_, {unknown}, _> - st Foo<…> Foo<'_, {unknown}, _> + sp Self Foo<{unknown}, _, 'static> + st Foo<…> Foo<{unknown}, _, 'static> st Record Record st Tuple Tuple st Unit Unit @@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0); en Enum Enum ma makro!(…) macro_rules! makro md module - sp Self Foo<'_, {unknown}, _> - st Foo<…> Foo<'_, {unknown}, _> + sp Self Foo<{unknown}, _, 'static> + st Foo<…> Foo<{unknown}, _, 'static> st Record Record st Tuple Tuple st Unit Unit From 8d08b337fa023a8db4fe6b8dd74eed0efea4e7f1 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Tue, 12 Mar 2024 00:05:37 +0530 Subject: [PATCH 08/12] include lifetime in the filter for data layout in analysis-stats clippy fixes --- crates/hir-ty/src/lower.rs | 2 +- crates/hir-ty/src/utils.rs | 4 ++-- crates/rust-analyzer/src/cli/analysis_stats.rs | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 9370a2cee04..63772fb7c1c 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1784,7 +1784,7 @@ pub(crate) fn generic_defaults_query( }; let mut val = p.default.as_ref().map_or_else( - || unknown_const_as_generic(db.const_param_ty(id.into())), + || unknown_const_as_generic(db.const_param_ty(id)), |c| { let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); c.cast(Interner) diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index cadb099c2b8..af5f7bb42a5 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -480,10 +480,10 @@ impl Generics { crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner) } GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into()) - .to_const(Interner, db.const_param_ty(id.into())) + .to_const(Interner, db.const_param_ty(id)) .cast(Interner), GenericParamId::LifetimeParamId(id) => { - crate::lt_to_placeholder_idx(db, id.into()).to_lifetime(Interner).cast(Interner) + crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner) } }), ) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 5c474908e7a..d4e8dcadbd8 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -279,7 +279,8 @@ impl flags::AnalysisStats { let mut all = 0; let mut fail = 0; for &a in adts { - if db.generic_params(a.into()).iter().next().is_some() { + let generic_params = db.generic_params(a.into()); + if generic_params.iter().next().is_some() || generic_params.iter_lt().next().is_some() { // Data types with generics don't have layout. continue; } From a555e95c9af0490e03c7714937667f99b7a5f388 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 13 Mar 2024 21:07:20 +0530 Subject: [PATCH 09/12] fix make HirDisplay format lifetimes first --- crates/hir-ty/src/display.rs | 25 ++++++++++++++++--- crates/hir-ty/src/tests/regression.rs | 4 +-- .../src/handlers/extract_function.rs | 2 +- .../src/handlers/generate_delegate_methods.rs | 2 +- crates/ide-completion/src/tests/predicate.rs | 4 +-- crates/ide-completion/src/tests/type_pos.rs | 8 +++--- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index bc5bd791696..f472a5d7f22 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -3,6 +3,7 @@ //! purposes. use std::{ + cmp::Ordering, fmt::{self, Debug}, mem::size_of, }; @@ -953,11 +954,17 @@ impl HirDisplay for Ty { // `parameters` are in the order of fn's params (including impl traits), // parent's params (those from enclosing impl or trait, if any). let parameters = parameters.as_slice(Interner); - let fn_params_len = - self_param + type_params + const_params + lifetime_params; + let fn_params_len = self_param + type_params + const_params; + // This will give slice till last type or const let fn_params = parameters.get(..fn_params_len); + let fn_lt_params = + parameters.get(fn_params_len..(fn_params_len + lifetime_params)); let parent_params = parameters.get(parameters.len() - parent_params..); - let params = parent_params.into_iter().chain(fn_params).flatten(); + let params = parent_params + .into_iter() + .chain(fn_lt_params) + .chain(fn_params) + .flatten(); write!(f, "<")?; f.write_joined(params, ", ")?; write!(f, ">")?; @@ -1317,6 +1324,15 @@ fn hir_fmt_generics( ) -> Result<(), HirDisplayError> { let db = f.db; if parameters.len(Interner) > 0 { + let param_compare = + |a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) { + (crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => { + Ordering::Equal + } + (crate::GenericArgData::Lifetime(_), _) => Ordering::Less, + (_, crate::GenericArgData::Lifetime(_)) => Ordering::Less, + (_, _) => Ordering::Equal, + }; let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() { match generic_def .map(|generic_def_id| db.generic_defaults(generic_def_id)) @@ -1367,6 +1383,9 @@ fn hir_fmt_generics( } else { parameters.as_slice(Interner) }; + //FIXME: Should handle when creating substitutions + let mut parameters_to_write = parameters_to_write.to_vec(); + parameters_to_write.sort_by(param_compare); if !parameters_to_write.is_empty() { write!(f, "<")?; let mut first = true; diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index af016db4dc5..8565b60210b 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -896,13 +896,13 @@ fn flush(&self) { "#, expect![[r#" 123..127 'self': &Mutex - 150..152 '{}': MutexGuard + 150..152 '{}': MutexGuard<'static, T> 234..238 'self': &{unknown} 240..290 '{ ...()); }': () 250..251 'w': &Mutex 276..287 '*(w.lock())': BufWriter 278..279 'w': &Mutex - 278..286 'w.lock()': MutexGuard + 278..286 'w.lock()': MutexGuard<'static, BufWriter> "#]], ); } diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 981eb18b58f..65ce3e822c5 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -5617,7 +5617,7 @@ fn func(i: Struct<'_, T>) { fun_name(i); } -fn $0fun_name(i: Struct) { +fn $0fun_name(i: Struct<'static, T>) { foo(i); } "#, diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs index 78d3fa11672..2150003bc14 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -614,7 +614,7 @@ struct Foo<'a, T> { } impl<'a, T> Foo<'a, T> { - $0fn bar(self, mut b: Vec<&'a Bar>) -> &'a Bar { + $0fn bar(self, mut b: Vec<&'a Bar<'a, T>>) -> &'a Bar<'a, T> { self.field.bar(b) } } diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs index e7f3eeaecbc..3718dff56e8 100644 --- a/crates/ide-completion/src/tests/predicate.rs +++ b/crates/ide-completion/src/tests/predicate.rs @@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {} en Enum Enum ma makro!(…) macro_rules! makro md module - st Foo<…> Foo<{unknown}, _, 'static> + st Foo<…> Foo<'static, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit @@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {} en Enum Enum ma makro!(…) macro_rules! makro md module - st Foo<…> Foo<{unknown}, _, 'static> + st Foo<…> Foo<'static, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 60ee7bf4e67..97709728656 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> { en Enum Enum ma makro!(…) macro_rules! makro md module - sp Self Foo<{unknown}, _, 'static> - st Foo<…> Foo<{unknown}, _, 'static> + sp Self Foo<'static, {unknown}, _> + st Foo<…> Foo<'static, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit @@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0); en Enum Enum ma makro!(…) macro_rules! makro md module - sp Self Foo<{unknown}, _, 'static> - st Foo<…> Foo<{unknown}, _, 'static> + sp Self Foo<'static, {unknown}, _> + st Foo<…> Foo<'static, {unknown}, _> st Record Record st Tuple Tuple st Unit Unit From 13301e7a1ae26214a038a6c344df9d85b895b540 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 18 Mar 2024 15:48:59 +0530 Subject: [PATCH 10/12] replace static_lifetime with new_lifetime_var where necessary implemented suggested fixes and changes and fix merge conflicts --- crates/hir-def/src/resolver.rs | 15 +++++---------- crates/hir-ty/src/builder.rs | 9 ++++----- crates/hir-ty/src/display.rs | 4 ++-- crates/hir-ty/src/infer/expr.rs | 5 +++-- crates/hir-ty/src/lower.rs | 9 +++++---- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index bfad75c50b6..fadab858aa1 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -430,17 +430,12 @@ impl Resolver { return Some(LifetimeNs::Static); } - for scope in self.scopes() { - match scope { - Scope::GenericParams { def, params } => { - if let Some(id) = params.find_lifetime_by_name(&lifetime.name, *def) { - return Some(LifetimeNs::LifetimeParam(id)); - } - } - _ => continue, + self.scopes().find_map(|scope| match scope { + Scope::GenericParams { def, params } => { + params.find_lifetime_by_name(&lifetime.name, *def).map(LifetimeNs::LifetimeParam) } - } - None + _ => None, + }) } /// Returns a set of names available in the current scope. diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index 536542f9a07..cb118a36848 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -15,9 +15,9 @@ use smallvec::SmallVec; use crate::{ consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, - infer::unify::InferenceTable, primitive, static_lifetime, to_assoc_type_id, to_chalk_trait_id, - utils::generics, Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, - ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind, + infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, + Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, + Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -134,8 +134,7 @@ impl TyBuilder { self.fill(|x| match x { ParamKind::Type => table.new_type_var().cast(Interner), ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner), - // FIXME: create new_lifetime_var in table - ParamKind::Lifetime => static_lifetime().cast(Interner), + ParamKind::Lifetime => table.new_lifetime_var().cast(Interner), }) } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index f472a5d7f22..abac3447035 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -951,7 +951,7 @@ impl HirDisplay for Ty { parent_params + self_param + type_params + const_params + lifetime_params; // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? if total_len > 0 { - // `parameters` are in the order of fn's params (including impl traits), + // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes // parent's params (those from enclosing impl or trait, if any). let parameters = parameters.as_slice(Interner); let fn_params_len = self_param + type_params + const_params; @@ -1383,7 +1383,7 @@ fn hir_fmt_generics( } else { parameters.as_slice(Interner) }; - //FIXME: Should handle when creating substitutions + //FIXME: Should handle the ordering of lifetimes when creating substitutions let mut parameters_to_write = parameters_to_write.to_vec(); parameters_to_write.sort_by(param_compare); if !parameters_to_write.is_empty() { diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 82f7e87ac91..aab052fdf16 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1873,8 +1873,9 @@ impl InferenceContext<'_> { 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)), + GenericParamId::LifetimeParamId(_) => { + substs.push(self.table.new_lifetime_var().cast(Interner)) + } } } assert_eq!(substs.len(), total_len); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 63772fb7c1c..b4ff98a63c6 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -18,6 +18,7 @@ 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, @@ -279,6 +280,7 @@ impl<'a> TyLoweringContext<'a> { } TypeRef::Reference(inner, lifetime, mutability) => { let inner_ty = self.lower_ty(inner); + // FIXME: It should infer the eldided lifetimes instead of stubbing with static let lifetime = lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr)); TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty) @@ -863,9 +865,9 @@ impl<'a> TyLoweringContext<'a> { fill_self_params(); } let expected_num = if generic_args.has_self_type { - self_params + type_params + const_params + lifetime_params + self_params + type_params + const_params } else { - type_params + const_params + lifetime_params + type_params + const_params }; let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; // if args are provided, it should be all of them, but we can't rely on that @@ -899,8 +901,7 @@ impl<'a> TyLoweringContext<'a> { .args .iter() .filter(|arg| matches!(arg, GenericArg::Lifetime(_))) - .skip(skip) - .take(expected_num) + .take(lifetime_params) { // Taking into the fact that def_generic_iter will always have lifetimes at the end // Should have some test cases tho to test this behaviour more properly From b357bcab2beb3533d3059b4c8723e4729a4333e2 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Tue, 19 Mar 2024 10:14:45 +0530 Subject: [PATCH 11/12] modify `insert_type_vars` for lifetimes --- crates/hir-ty/src/infer.rs | 8 +++++- crates/hir-ty/src/infer/expr.rs | 3 +- crates/hir-ty/src/infer/unify.rs | 25 +++++++++------- crates/hir-ty/src/lib.rs | 49 ++++++++++++++++++++++++++++++++ crates/hir-ty/src/lower.rs | 2 +- 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 29e12799451..be3b50e1411 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -42,7 +42,7 @@ use hir_def::{ layout::Integer, path::{ModPath, Path}, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, - type_ref::TypeRef, + type_ref::{LifetimeRef, TypeRef}, AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, }; @@ -1037,6 +1037,12 @@ impl<'a> InferenceContext<'a> { self.result.standard_types.unknown.clone() } + fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime { + let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()); + let lt = ctx.lower_lifetime(lifetime_ref); + self.insert_type_vars(lt) + } + /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it. fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { self.table.insert_type_vars_shallow(ty) diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index aab052fdf16..35d59679355 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1855,8 +1855,7 @@ impl InferenceContext<'_> { DebruijnIndex::INNERMOST, ) }, - // FIXME: create make_lifetimes and infer lifetimes - |_, _| static_lifetime(), + |this, lt_ref| this.make_lifetime(lt_ref), ) { substs.push(g); } diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index a6c5666911a..afb89fe1e5b 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -16,12 +16,12 @@ use triomphe::Arc; use super::{InferOk, InferResult, InferenceContext, TypeError}; use crate::{ - consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime, - to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, - DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment, - InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, - Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind, - WhereClause, + consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, + static_lifetime, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, + Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, + Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, + ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, + TyKind, VariableKind, WhereClause, }; impl InferenceContext<'_> { @@ -862,11 +862,16 @@ impl<'a> InferenceTable<'a> { where T: HasInterner + TypeFoldable, { - fold_tys_and_consts( + fold_generic_args( ty, - |it, _| match it { - Either::Left(ty) => Either::Left(self.insert_type_vars_shallow(ty)), - Either::Right(c) => Either::Right(self.insert_const_vars_shallow(c)), + |arg, _| match arg { + GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)), + // FIXME: insert lifetime vars once LifetimeData::InferenceVar + // and specific error variant for lifetimes start being constructed + GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt), + GenericArgData::Const(c) => { + GenericArgData::Const(self.insert_const_vars_shallow(c)) + } }, DebruijnIndex::INNERMOST, ) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index fc7ed79f5cf..e217cf3d09d 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -716,6 +716,55 @@ pub(crate) fn fold_tys_and_consts + TypeFold t.fold_with(&mut TyFolder(f), binders) } +pub(crate) fn fold_generic_args + TypeFoldable>( + t: T, + f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData, + binders: DebruijnIndex, +) -> T { + use chalk_ir::fold::{TypeFolder, TypeSuperFoldable}; + #[derive(chalk_derive::FallibleTypeFolder)] + #[has_interner(Interner)] + struct TyFolder GenericArgData>(F); + impl GenericArgData> TypeFolder + for TyFolder + { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { + self + } + + fn interner(&self) -> Interner { + Interner + } + + fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty { + let ty = ty.super_fold_with(self.as_dyn(), outer_binder); + self.0(GenericArgData::Ty(ty), outer_binder) + .intern(Interner) + .ty(Interner) + .unwrap() + .clone() + } + + fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const { + self.0(GenericArgData::Const(c), outer_binder) + .intern(Interner) + .constant(Interner) + .unwrap() + .clone() + } + + fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime { + let lt = lt.super_fold_with(self.as_dyn(), outer_binder); + self.0(GenericArgData::Lifetime(lt), outer_binder) + .intern(Interner) + .lifetime(Interner) + .unwrap() + .clone() + } + } + t.fold_with(&mut TyFolder(f), binders) +} + /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also /// ensures there are no unbound variables or inference variables anywhere in /// the `t`. diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index b4ff98a63c6..d0d30fd570c 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1362,7 +1362,7 @@ impl<'a> TyLoweringContext<'a> { ImplTrait { bounds: crate::make_single_type_binders(predicates) } } - fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime { + pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime { match self.resolver.resolve_lifetime(lifetime) { Some(resolution) => match resolution { LifetimeNs::Static => static_lifetime(), From 0e54e2b55ac3d2ddec269978c86787e7320aaa7a Mon Sep 17 00:00:00 2001 From: dfireBird Date: Tue, 19 Mar 2024 12:57:18 +0530 Subject: [PATCH 12/12] use references in Generics iter methods --- crates/hir-def/src/generics.rs | 6 +++++ crates/hir-ty/src/display.rs | 2 +- crates/hir-ty/src/lower.rs | 10 ++++---- crates/hir-ty/src/utils.rs | 43 +++++++++++++++++----------------- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index c141acd2ec4..4bc86623dfb 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -142,6 +142,12 @@ impl GenericParamData { impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData); +pub enum GenericParamDataRef<'a> { + TypeParamData(&'a TypeParamData), + ConstParamData(&'a ConstParamData), + LifetimeParamData(&'a LifetimeParamData), +} + /// 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/display.rs b/crates/hir-ty/src/display.rs index abac3447035..8740ae6797c 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -3,7 +3,6 @@ //! purposes. use std::{ - cmp::Ordering, fmt::{self, Debug}, mem::size_of, }; @@ -1324,6 +1323,7 @@ fn hir_fmt_generics( ) -> Result<(), HirDisplayError> { let db = f.db; if parameters.len(Interner) > 0 { + use std::cmp::Ordering; let param_compare = |a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) { (crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => { diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index d0d30fd570c..25ccc84c13c 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -24,7 +24,7 @@ use hir_def::{ data::adt::StructKind, expander::Expander, generics::{ - GenericParamData, TypeOrConstParamData, TypeParamProvenance, WherePredicate, + GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, }, lang_item::LangItem, @@ -356,7 +356,7 @@ impl<'a> TyLoweringContext<'a> { .filter(|(_, data)| { matches!( data, - GenericParamData::TypeParamData(data) + GenericParamDataRef::TypeParamData(data) if data.provenance == TypeParamProvenance::ArgumentImplTrait ) }) @@ -1770,7 +1770,7 @@ pub(crate) fn generic_defaults_query( let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| { match p { - GenericParamData::TypeParamData(p) => { + GenericParamDataRef::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. @@ -1779,7 +1779,7 @@ pub(crate) fn generic_defaults_query( ty = fallback_bound_vars(ty, idx, parent_start_idx); crate::make_binders(db, &generic_params, ty.cast(Interner)) } - GenericParamData::ConstParamData(p) => { + GenericParamDataRef::ConstParamData(p) => { let GenericParamId::ConstParamId(id) = id else { unreachable!("Unexpected lifetime or type argument") }; @@ -1795,7 +1795,7 @@ pub(crate) fn generic_defaults_query( val = fallback_bound_vars(val, idx, parent_start_idx); make_binders(db, &generic_params, val) } - GenericParamData::LifetimeParamData(_) => { + GenericParamDataRef::LifetimeParamData(_) => { // using static because it requires defaults make_binders(db, &generic_params, static_lifetime().cast(Interner)) } diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index af5f7bb42a5..9b8a3e2dfbf 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -12,7 +12,7 @@ use chalk_ir::{ use hir_def::{ db::DefDatabase, generics::{ - GenericParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, + GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, }, lang_item::LangItem, @@ -277,28 +277,28 @@ impl Generics { /// Iterator over types and const params of self, then parent. pub(crate) fn iter<'a>( &'a self, - ) -> impl DoubleEndedIterator + 'a { + ) -> impl DoubleEndedIterator)> + 'a { let from_toc_id = |it: &'a Generics| { - move |(local_id, p): (_, &TypeOrConstParamData)| { + move |(local_id, p): (_, &'a TypeOrConstParamData)| { let id = TypeOrConstParamId { parent: it.def, local_id }; match p { TypeOrConstParamData::TypeParamData(p) => ( GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)), - GenericParamData::TypeParamData(p.clone()), + GenericParamDataRef::TypeParamData(p), ), TypeOrConstParamData::ConstParamData(p) => ( GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)), - GenericParamData::ConstParamData(p.clone()), + GenericParamDataRef::ConstParamData(p), ), } } }; let from_lt_id = |it: &'a Generics| { - move |(local_id, p): (_, &LifetimeParamData)| { + move |(local_id, p): (_, &'a LifetimeParamData)| { ( GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }), - GenericParamData::LifetimeParamData(p.clone()), + GenericParamDataRef::LifetimeParamData(p), ) } }; @@ -310,28 +310,28 @@ impl Generics { /// Iterate over types and const params without parent params. pub(crate) fn iter_self<'a>( &'a self, - ) -> impl DoubleEndedIterator + 'a { + ) -> impl DoubleEndedIterator)> + 'a { let from_toc_id = |it: &'a Generics| { - move |(local_id, p): (_, &TypeOrConstParamData)| { + move |(local_id, p): (_, &'a TypeOrConstParamData)| { let id = TypeOrConstParamId { parent: it.def, local_id }; match p { TypeOrConstParamData::TypeParamData(p) => ( GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)), - GenericParamData::TypeParamData(p.clone()), + GenericParamDataRef::TypeParamData(p), ), TypeOrConstParamData::ConstParamData(p) => ( GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)), - GenericParamData::ConstParamData(p.clone()), + GenericParamDataRef::ConstParamData(p), ), } } }; let from_lt_id = |it: &'a Generics| { - move |(local_id, p): (_, &LifetimeParamData)| { + move |(local_id, p): (_, &'a LifetimeParamData)| { ( GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }), - GenericParamData::LifetimeParamData(p.clone()), + GenericParamDataRef::LifetimeParamData(p), ) } }; @@ -340,28 +340,29 @@ impl Generics { } /// Iterator over types and const params of parent. - pub(crate) fn iter_parent( - &self, - ) -> impl DoubleEndedIterator + '_ { + #[allow(clippy::needless_lifetimes)] + pub(crate) fn iter_parent<'a>( + &'a self, + ) -> impl DoubleEndedIterator)> + 'a { self.parent_generics().into_iter().flat_map(|it| { - let from_toc_id = move |(local_id, p): (_, &TypeOrConstParamData)| { + let from_toc_id = move |(local_id, p): (_, &'a TypeOrConstParamData)| { let id = TypeOrConstParamId { parent: it.def, local_id }; match p { TypeOrConstParamData::TypeParamData(p) => ( GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)), - GenericParamData::TypeParamData(p.clone()), + GenericParamDataRef::TypeParamData(p), ), TypeOrConstParamData::ConstParamData(p) => ( GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)), - GenericParamData::ConstParamData(p.clone()), + GenericParamDataRef::ConstParamData(p), ), } }; - let from_lt_id = move |(local_id, p): (_, &LifetimeParamData)| { + let from_lt_id = move |(local_id, p): (_, &'a LifetimeParamData)| { ( GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }), - GenericParamData::LifetimeParamData(p.clone()), + GenericParamDataRef::LifetimeParamData(p), ) }; let lt_iter = it.params.iter_lt().map(from_lt_id);