Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 257 |
1 files changed, 104 insertions, 153 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 96f545415e..d421e72d36 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -11,10 +11,7 @@ use std::{ ops::{self, Not as _}, }; -use base_db::{ - salsa::{Cycle, InternValueTrivial}, - CrateId, -}; +use base_db::{salsa::Cycle, CrateId}; use chalk_ir::{ cast::Cast, fold::{Shift, TypeFoldable}, @@ -38,10 +35,10 @@ use hir_def::{ type_ref::{ ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, }, - AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, - Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, - UnionId, VariantId, + AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, + LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, + TypeOwnerId, UnionId, VariantId, }; use hir_expand::{name::Name, ExpandResult}; use intern::Interned; @@ -387,14 +384,18 @@ impl<'a> TyLoweringContext<'a> { type_params, const_params, _impl_trait_params, - _lifetime_params, + lifetime_params, ) = self .generics() .expect("variable impl trait lowering must be in a generic def") .provenance_split(); TyKind::BoundVar(BoundVar::new( self.in_binders, - idx as usize + self_param as usize + type_params + const_params, + idx as usize + + self_param as usize + + type_params + + const_params + + lifetime_params, )) .intern(Interner) } @@ -815,13 +816,13 @@ impl<'a> TyLoweringContext<'a> { infer_args: bool, explicit_self_ty: Option<Ty>, ) -> Substitution { - // Remember that the item's own generic args come before its parent's. - let mut substs = Vec::new(); - let def = if let Some(d) = def { - d - } else { - return Substitution::empty(Interner); - }; + let Some(def) = def else { return Substitution::empty(Interner) }; + + // Order is + // - Optional Self parameter + // - Lifetime parameters + // - Type or Const parameters + // - Parent parameters let def_generics = generics(self.db.upcast(), def); let ( parent_params, @@ -835,130 +836,121 @@ impl<'a> TyLoweringContext<'a> { self_param as usize + 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 substs = Vec::new(); - let mut def_generic_iter = def_generics.iter_id(); + // we need to iterate the lifetime and type/const params separately as our order of them + // differs from the supplied syntax - let fill_self_params = || { + let ty_error = || TyKind::Error.intern(Interner).cast(Interner); + let mut def_toc_iter = def_generics.iter_self_type_or_consts_id(); + let fill_self_param = || { if self_param { - let self_ty = - explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(|| ty_error.clone()); + let self_ty = explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(ty_error); - if let Some(id) = def_generic_iter.next() { - assert!(matches!( - id, - GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_) - )); + if let Some(id) = def_toc_iter.next() { + assert!(matches!(id, GenericParamId::TypeParamId(_))); substs.push(self_ty); } } }; let mut had_explicit_args = false; - if let Some(generic_args) = &args_and_bindings { - if !generic_args.has_self_type { - fill_self_params(); - } - let expected_num = if generic_args.has_self_type { - self_param as usize + type_params + const_params + if let Some(&GenericArgs { ref args, has_self_type, .. }) = args_and_bindings { + // Fill in the self param first + if has_self_type && self_param { + had_explicit_args = true; + if let Some(id) = def_toc_iter.next() { + assert!(matches!(id, GenericParamId::TypeParamId(_))); + had_explicit_args = true; + if let GenericArg::Type(ty) = &args[0] { + substs.push(self.lower_ty(ty).cast(Interner)); + } + } } else { - type_params + const_params + fill_self_param() }; - let skip = if generic_args.has_self_type && !self_param { 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 + + // Then fill in the supplied lifetime args, or error lifetimes if there are too few + // (default lifetimes aren't a thing) + for arg in args .iter() - .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) - .skip(skip) - .take(expected_num) + .filter_map(|arg| match arg { + GenericArg::Lifetime(arg) => Some(self.lower_lifetime(arg)), + _ => None, + }) + .chain(iter::repeat(error_lifetime())) + .take(lifetime_params) { - if let Some(id) = def_generic_iter.next() { - let arg = 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(arg); - } + substs.push(arg.cast(Interner)); } - for arg in generic_args - .args + let skip = if has_self_type { 1 } else { 0 }; + // Fill in supplied type and const args + // Note if non-lifetime args are provided, it should be all of them, but we can't rely on that + for (arg, id) in args .iter() - .filter(|arg| matches!(arg, GenericArg::Lifetime(_))) - .take(lifetime_params) + .filter(|arg| !matches!(arg, GenericArg::Lifetime(_))) + .skip(skip) + .take(type_params + const_params) + .zip(def_toc_iter) { - // 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() { - let arg = 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(arg); - } + had_explicit_args = true; + let arg = 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), + ); + substs.push(arg); } } else { - fill_self_params(); + fill_self_param(); } - // These params include those of parent. - let remaining_params: SmallVec<[_; 2]> = def_generic_iter - .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); - + let param_to_err = |id| match id { + GenericParamId::ConstParamId(x) => unknown_const_as_generic(self.db.const_param_ty(x)), + GenericParamId::TypeParamId(_) => ty_error(), + GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), + }; // handle defaults. In expression or pattern path segments without // explicitly specified type arguments, missing type arguments are inferred // (i.e. defaults aren't used). // Generic parameters for associated types are not supposed to have defaults, so we just // ignore them. - let is_assoc_ty = if let GenericDefId::TypeAliasId(id) = def { - let container = id.lookup(self.db.upcast()).container; - matches!(container, ItemContainerId::TraitId(_)) - } else { - false + let is_assoc_ty = || match def { + GenericDefId::TypeAliasId(id) => { + matches!(id.lookup(self.db.upcast()).container, ItemContainerId::TraitId(_)) + } + _ => false, }; - if !is_assoc_ty && (!infer_args || had_explicit_args) { - let defaults = self.db.generic_defaults(def); - assert_eq!(total_len, defaults.len()); + let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty(); + if fill_defaults { + let defaults = &*self.db.generic_defaults(def); + let (item, _parent) = defaults.split_at(item_len); let parent_from = item_len - substs.len(); - for (idx, default_ty) in defaults[substs.len()..item_len].iter().enumerate() { + let mut rem = + def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::<Vec<_>>(); + // Fill in defaults for type/const params + for (idx, default_ty) in item[substs.len()..].iter().enumerate() { // each default can depend on the previous parameters let substs_so_far = Substitution::from_iter( Interner, - substs.iter().cloned().chain(remaining_params[idx..].iter().cloned()), + substs.iter().cloned().chain(rem[idx..].iter().cloned()), ); substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); } - - // Keep parent's params as unknown. - let mut remaining_params = remaining_params; - substs.extend(remaining_params.drain(parent_from..)); + // Fill in remaining parent params + substs.extend(rem.drain(parent_from..)); } else { - substs.extend(remaining_params); + // Fill in remaining def params and parent params + substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err)); } - assert_eq!(substs.len(), total_len); + assert_eq!(substs.len(), total_len, "expected {} substs, got {}", total_len, substs.len()); Substitution::from_iter(Interner, substs) } @@ -1535,7 +1527,7 @@ pub(crate) fn generic_predicates_for_param_query( def: GenericDefId, param_id: TypeOrConstParamId, assoc_name: Option<Name>, -) -> Arc<[Binders<QuantifiedWhereClause>]> { +) -> GenericPredicates { let resolver = def.resolver(db.upcast()); let ctx = if let GenericDefId::FunctionId(_) = def { TyLoweringContext::new(db, &resolver, def.into()) @@ -1611,7 +1603,7 @@ pub(crate) fn generic_predicates_for_param_query( ); }; } - predicates.into() + GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) } pub(crate) fn generic_predicates_for_param_recover( @@ -1620,15 +1612,15 @@ pub(crate) fn generic_predicates_for_param_recover( _def: &GenericDefId, _param_id: &TypeOrConstParamId, _assoc_name: &Option<Name>, -) -> Arc<[Binders<QuantifiedWhereClause>]> { - Arc::from_iter(None) +) -> GenericPredicates { + GenericPredicates(None) } pub(crate) fn trait_environment_for_body_query( db: &dyn HirDatabase, def: DefWithBodyId, ) -> Arc<TraitEnvironment> { - let Some(def) = def.as_generic_def_id() else { + let Some(def) = def.as_generic_def_id(db.upcast()) else { let krate = def.module(db.upcast()).krate(); return TraitEnvironment::empty(krate); }; @@ -1725,8 +1717,8 @@ pub(crate) fn generic_predicates_query( }) .collect::<Vec<_>>(); - let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - if !subst.is_empty(Interner) { + if generics.len() > 0 { + let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); let explicitly_unsized_tys = ctx.unsized_types.into_inner(); if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) @@ -1995,47 +1987,6 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum CallableDefId { - FunctionId(FunctionId), - StructId(StructId), - EnumVariantId(EnumVariantId), -} - -impl InternValueTrivial for CallableDefId {} - -impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId); -impl From<CallableDefId> for ModuleDefId { - fn from(def: CallableDefId) -> ModuleDefId { - match def { - CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f), - CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)), - CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e), - } - } -} - -impl CallableDefId { - pub fn krate(self, db: &dyn HirDatabase) -> CrateId { - let db = db.upcast(); - match self { - CallableDefId::FunctionId(f) => f.krate(db), - CallableDefId::StructId(s) => s.krate(db), - CallableDefId::EnumVariantId(e) => e.krate(db), - } - } -} - -impl From<CallableDefId> for GenericDefId { - fn from(def: CallableDefId) -> GenericDefId { - match def { - CallableDefId::FunctionId(f) => f.into(), - CallableDefId::StructId(s) => s.into(), - CallableDefId::EnumVariantId(e) => e.into(), - } - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum TyDefId { BuiltinType(BuiltinType), @@ -2056,12 +2007,12 @@ pub enum ValueTyDefId { impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId); impl ValueTyDefId { - pub(crate) fn to_generic_def_id(self) -> Option<GenericDefId> { + pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> Option<GenericDefId> { match self { Self::FunctionId(id) => Some(id.into()), Self::StructId(id) => Some(id.into()), Self::UnionId(id) => Some(id.into()), - Self::EnumVariantId(var) => Some(var.into()), + Self::EnumVariantId(var) => Some(var.lookup(db.upcast()).parent.into()), Self::ConstId(id) => Some(id.into()), Self::StaticId(_) => None, } @@ -2112,7 +2063,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde // returns None if def is a type arg pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { let parent_data = db.generic_params(def.parent()); - let data = &parent_data.type_or_consts[def.local_id()]; + let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, def.parent().into()); match data { |