diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 515fc4c668..e951048021 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -21,12 +21,12 @@ use crate::{ chalk_db, consteval::ConstEvalError, layout::{Layout, LayoutError}, - lower::GenericPredicates, + lower::{GenericDefaults, GenericPredicates}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, - Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, ImplTraits, - InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, - TraitRef, Ty, TyDefId, ValueTyDefId, + Binders, CallableDefId, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, + Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, TraitRef, Ty, + TyDefId, ValueTyDefId, }; use hir_expand::name::Name; @@ -159,7 +159,7 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::lower::generic_defaults_query)] #[salsa::cycle(crate::lower::generic_defaults_recover)] - fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders]>; + fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc; diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 685aceb233..257d6c71fd 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -330,18 +330,15 @@ pub(crate) fn make_single_type_binders>( ) } -pub(crate) fn make_binders_with_count>( +pub(crate) fn make_binders>( db: &dyn HirDatabase, - count: usize, generics: &Generics, value: T, ) -> Binders { - let it = generics.iter_id().take(count); - Binders::new( VariableKinds::from_iter( Interner, - it.map(|x| match x { + generics.iter_id().map(|x| match x { hir_def::GenericParamId::ConstParamId(id) => { chalk_ir::VariableKind::Const(db.const_param_ty(id)) } @@ -355,14 +352,6 @@ pub(crate) fn make_binders_with_count>( ) } -pub(crate) fn make_binders>( - db: &dyn HirDatabase, - generics: &Generics, - value: T, -) -> Binders { - make_binders_with_count(db, usize::MAX, generics, value) -} - // FIXME: get rid of this, just replace it by FnPointer /// A function signature as seen by type inference: Several parameter types and /// one return type. diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 4942244396..ac2eae03e6 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -8,7 +8,7 @@ use std::{ cell::{Cell, RefCell, RefMut}, iter, - ops::Not as _, + ops::{self, Not as _}, }; use base_db::{ @@ -1693,9 +1693,11 @@ pub(crate) fn trait_environment_query( #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericPredicates(Option]>>); -impl GenericPredicates { - pub fn iter(&self) -> impl Iterator> + '_ + Clone { - self.0.as_ref().into_iter().flat_map(Arc::as_ref) +impl ops::Deref for GenericPredicates { + type Target = [Binders]; + + fn deref(&self) -> &Self::Target { + self.0.as_deref().unwrap_or(&[]) } } @@ -1767,68 +1769,84 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>( }) } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericDefaults(Option]>>); + +impl ops::Deref for GenericDefaults { + type Target = [Binders]; + + fn deref(&self) -> &Self::Target { + self.0.as_deref().unwrap_or(&[]) + } +} + /// Resolve the default type params from generics -pub(crate) fn generic_defaults_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> Arc<[Binders]> { - let resolver = def.resolver(db.upcast()); +pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults { let generic_params = generics(db.upcast(), def); + if generic_params.len() == 0 { + return GenericDefaults(None); + } + let resolver = def.resolver(db.upcast()); let parent_start_idx = generic_params.len_self(); let ctx = TyLoweringContext::new(db, &resolver, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) .with_type_param_mode(ParamLoweringMode::Variable); - Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| { - match 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. - // Type variable default referring to parameter coming - // after it is forbidden (FIXME: report diagnostic) - ty = fallback_bound_vars(ty, idx, parent_start_idx); - crate::make_binders(db, &generic_params, ty.cast(Interner)) - } - GenericParamDataRef::ConstParamData(p) => { - let GenericParamId::ConstParamId(id) = id else { - unreachable!("Unexpected lifetime or type argument") - }; + GenericDefaults(Some(Arc::from_iter(generic_params.iter().enumerate().map( + |(idx, (id, p))| { + match p { + GenericParamDataRef::TypeParamData(p) => { + let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| { + // Each default can only refer to previous parameters. + // Type variable default referring to parameter coming + // after it is forbidden (FIXME: report diagnostic) + fallback_bound_vars(ctx.lower_ty(ty), idx, parent_start_idx) + }); + crate::make_binders(db, &generic_params, ty.cast(Interner)) + } + GenericParamDataRef::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(id)), - |c| { - let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); - c.cast(Interner) - }, - ); - // Each default can only refer to previous parameters, see above. - val = fallback_bound_vars(val, idx, parent_start_idx); - make_binders(db, &generic_params, val) + let mut val = p.default.as_ref().map_or_else( + || unknown_const_as_generic(db.const_param_ty(id)), + |c| { + let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); + c.cast(Interner) + }, + ); + // Each default can only refer to previous parameters, see above. + val = fallback_bound_vars(val, idx, parent_start_idx); + make_binders(db, &generic_params, val) + } + GenericParamDataRef::LifetimeParamData(_) => { + make_binders(db, &generic_params, error_lifetime().cast(Interner)) + } } - GenericParamDataRef::LifetimeParamData(_) => { - make_binders(db, &generic_params, error_lifetime().cast(Interner)) - } - } - })) + }, + )))) } pub(crate) fn generic_defaults_recover( db: &dyn HirDatabase, _cycle: &Cycle, def: &GenericDefId, -) -> Arc<[Binders]> { +) -> GenericDefaults { let generic_params = generics(db.upcast(), *def); + if generic_params.len() == 0 { + return GenericDefaults(None); + } // FIXME: this code is not covered in tests. // we still need one default per parameter - Arc::from_iter(generic_params.iter_id().map(|id| { + GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| { let val = match id { GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)), GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), }; crate::make_binders(db, &generic_params, val) - })) + })))) } fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {