diff --git a/Cargo.lock b/Cargo.lock index b017b37a38..2cf6731aad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -200,9 +200,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chalk-derive" -version = "0.100.0" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2d131019373f0d0d1f2af0abd4f719739f6583c1b33965112455f643a910af" +checksum = "feb14e3ff0ebac26d8e58b6ed1417afb60c4a0a44b6425546ee7eb9c75ebb336" dependencies = [ "proc-macro2", "quote", @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.100.0" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f114996bda14c0213f014a4ef31a7867dcf5f539a3900477fc6b20138e7a17b" +checksum = "72f0a61621a088af69fee8df39ec63cf5b6d0b9ab663a740cdeb376aabf2f244" dependencies = [ "bitflags 2.9.0", "chalk-derive", @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.100.0" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551e956e031c09057c7b21f17d48d91de99c9b6b6e34bceaf5e7202d71021268" +checksum = "cbd3415cc540015533aa4a8ad007696d585dd9c5f81e7c099872f1dd4bf14894" dependencies = [ "chalk-derive", "chalk-ir", @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.100.0" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7ca50181156ce649efe8e5dd00580f573651554e4dcd11afa4e2ac93f53324" +checksum = "747707b0c082b3ecf4b1ae28d0d8df708a46cddd22a386f9cc85a312a4de25ff" dependencies = [ "chalk-derive", "chalk-ir", diff --git a/Cargo.toml b/Cargo.toml index 1fdc6b3896..851235eb99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,10 +104,10 @@ arrayvec = "0.7.6" bitflags = "2.9.0" cargo_metadata = "0.19.2" camino = "1.1.9" -chalk-solve = { version = "0.100.0", default-features = false } -chalk-ir = "0.100.0" -chalk-recursive = { version = "0.100.0", default-features = false } -chalk-derive = "0.100.0" +chalk-solve = { version = "0.102.0", default-features = false } +chalk-ir = "0.102.0" +chalk-recursive = { version = "0.102.0", default-features = false } +chalk-derive = "0.102.0" crossbeam-channel = "0.5.15" dissimilar = "1.0.10" dot = "0.1.4" diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index 163510602b..8c3665dfc8 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -76,7 +76,7 @@ impl TyBuilder { } let subst = Substitution::from_iter( Interner, - self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()), + self.parent_subst.iter(Interner).cloned().chain(self.vec), ); (self.data, subst) } @@ -278,8 +278,10 @@ impl TyBuilder<()> { }; Substitution::from_iter( Interner, - self_subst - .chain(generics(db, parent).placeholder_subst(db).iter(Interner)) + generics(db, parent) + .placeholder_subst(db) + .iter(Interner) + .chain(self_subst) .cloned() .collect::>(), ) diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 24deb00b38..db23847e0b 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -55,6 +55,22 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { fn associated_ty_data(&self, id: AssocTypeId) -> Arc { self.db.associated_ty_data(from_assoc_type_id(id)) } + fn associated_ty_from_impl( + &self, + impl_id: chalk_ir::ImplId, + assoc_type_id: chalk_ir::AssocTypeId, + ) -> Option> { + let alias_id = from_assoc_type_id(assoc_type_id); + let trait_sig = self.db.type_alias_signature(alias_id); + self.db.impl_items(hir_def::ImplId::from_chalk(self.db, impl_id)).items.iter().find_map( + |(name, item)| match item { + AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => { + Some(TypeAliasAsValue(*alias).to_chalk(self.db)) + } + _ => None, + }, + ) + } fn trait_datum(&self, trait_id: TraitId) -> Arc { self.db.trait_datum(self.krate, trait_id) } @@ -467,12 +483,13 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { // `resume_type`, `yield_type`, and `return_type` of the coroutine in question. let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build(); + let len = subst.len(Interner); let input_output = rust_ir::CoroutineInputOutputDatum { - resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) + resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 3)) .intern(Interner), - yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1)) + yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 2)) .intern(Interner), - return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 2)) + return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 1)) .intern(Interner), // FIXME: calculate upvars upvars: vec![], @@ -619,10 +636,10 @@ pub(crate) fn associated_ty_data_query( .with_type_param_mode(crate::lower::ParamLoweringMode::Variable); let trait_subst = TyBuilder::subst_for_def(db, trait_, None) - .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self()) + .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0) .build(); let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst)) - .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0) + .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self()) .build(); let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner); @@ -1021,8 +1038,9 @@ pub(super) fn generic_predicate_to_inline_bound( } WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into()); - let (assoc_args, trait_args) = - projection_ty.substitution.as_slice(Interner).split_at(generics.len_self()); + let parent_len = generics.parent_generics().map_or(0, |g| g.len_self()); + let (trait_args, assoc_args) = + projection_ty.substitution.as_slice(Interner).split_at(parent_len); let (self_ty, args_no_self) = trait_args.split_first().expect("projection without trait self type"); if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in { diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index 0b304014db..0f0cf6ae7a 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -418,10 +418,9 @@ impl ProjectionTyExt for ProjectionTy { fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { // FIXME: something like `Split` trait from chalk-solve might be nice. let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into()); - let substitution = Substitution::from_iter( - Interner, - self.substitution.iter(Interner).skip(generics.len_self()), - ); + let parent_len = generics.parent_generics().map_or(0, |g| g.len_self()); + let substitution = + Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len)); TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution } } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 5950d7b8b8..93d427b966 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -621,9 +621,8 @@ impl HirDisplay for ProjectionTy { .name .display(f.db, f.edition()) )?; - let proj_params_count = - self.substitution.len(Interner) - trait_ref.substitution.len(Interner); - let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count]; + let proj_params = + &self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..]; hir_fmt_generics(f, proj_params, None, None) } } @@ -1196,27 +1195,31 @@ impl HirDisplay for Ty { // Normally, functions cannot have default parameters, but they can, // for function-like things such as struct names or enum variants. - // The former cannot have defaults but parents, and the later cannot have - // parents but defaults. - // So, if `parent_len` > 0, it have a parent and thus it doesn't have any - // default. Therefore, we shouldn't subtract defaults because those defaults - // are from their parents. - // And if `parent_len` == 0, either parents don't exists or they don't have - // any defaults. Thus, we can - and should - subtract defaults. - let without_impl = if parent_len > 0 { - params_len - parent_len - impl_ + // The former cannot have defaults but does have parents, + // but the latter cannot have parents but can have defaults. + // + // However, it's also true that *traits* can have defaults too. + // In this case, there can be no function params. + let parent_end = if parent_len > 0 { + // If `parent_len` > 0, then there cannot be defaults on the function + // and all defaults must come from the parent. + parent_len - defaults } else { - params_len - parent_len - impl_ - defaults + parent_len }; - // parent's params (those from enclosing impl or trait, if any). - let (fn_params, parent_params) = parameters.split_at(without_impl + impl_); + let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_; + let (parent_params, fn_params) = parameters.split_at(parent_end); write!(f, "<")?; hir_fmt_generic_arguments(f, parent_params, None)?; if !parent_params.is_empty() && !fn_params.is_empty() { write!(f, ", ")?; } - hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?; + hir_fmt_generic_arguments( + f, + &fn_params[..fn_params_no_impl_or_defaults], + None, + )?; write!(f, ">")?; } } @@ -1873,11 +1876,12 @@ fn write_bounds_like_dyn_trait( f.end_location_link(); let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self(); + let parent_len = proj.substitution.len(Interner) - proj_arg_count; if proj_arg_count > 0 { write!(f, "<")?; hir_fmt_generic_arguments( f, - &proj.substitution.as_slice(Interner)[..proj_arg_count], + &proj.substitution.as_slice(Interner)[parent_len..], None, )?; write!(f, ">")?; diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index d174da9997..42fe129f91 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -65,7 +65,7 @@ impl Generics { } pub(crate) fn iter_id(&self) -> impl Iterator + '_ { - self.iter_self_id().chain(self.iter_parent_id()) + self.iter_parent_id().chain(self.iter_self_id()) } pub(crate) fn iter_self_id(&self) -> impl Iterator + '_ { @@ -82,11 +82,11 @@ impl Generics { self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head) } - /// Iterate over the params followed by the parent params. + /// Iterate over the parent params followed by self params. pub(crate) fn iter( &self, ) -> impl DoubleEndedIterator)> + '_ { - self.iter_self().chain(self.iter_parent()) + self.iter_parent().chain(self.iter_self()) } pub(crate) fn iter_parents_with_store( @@ -166,13 +166,10 @@ impl Generics { if self.params.trait_self_param() == Some(param.local_id) { return Some(idx); } - Some(self.params.len_lifetimes() + idx) + Some(self.parent_generics().map_or(0, |g| g.len()) + self.params.len_lifetimes() + idx) } else { debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent)); - self.parent_generics() - .and_then(|g| g.find_type_or_const_param(param)) - // Remember that parent parameters come after parameters for self. - .map(|idx| self.len_self() + idx) + self.parent_generics().and_then(|g| g.find_type_or_const_param(param)) } } @@ -184,12 +181,14 @@ impl Generics { if lifetime.parent == self.def { let idx = lifetime.local_id.into_raw().into_u32() as usize; debug_assert!(idx <= self.params.len_lifetimes()); - Some(self.params.trait_self_param().is_some() as usize + idx) + Some( + self.parent_generics().map_or(0, |g| g.len()) + + self.params.trait_self_param().is_some() as usize + + idx, + ) } else { debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent)); - self.parent_generics() - .and_then(|g| g.find_lifetime(lifetime)) - .map(|idx| self.len_self() + idx) + self.parent_generics().and_then(|g| g.find_lifetime(lifetime)) } } @@ -253,8 +252,7 @@ pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> O let parent_def = parent_generic_def(db, def)?; let parent_params = db.generic_params(parent_def); let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize; - let self_params = db.generic_params(def); - Some(self_params.len() + parent_self_idx) + Some(parent_self_idx) } } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 068d9a59da..a5074b8688 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -2065,7 +2065,16 @@ impl InferenceContext<'_> { assert!(!has_self_param); // method shouldn't have another Self param let total_len = parent_params + type_params + const_params + impl_trait_params + lifetime_params; - let mut substs = Vec::with_capacity(total_len); + + let param_to_var = |id| match id { + GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner), + GenericParamId::ConstParamId(id) => { + self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner) + } + GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner), + }; + + let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_var).collect(); // handle provided arguments if let Some(generic_args) = generic_args { @@ -2105,20 +2114,17 @@ 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 id { - GenericParamId::TypeParamId(_) => { - substs.push(self.table.new_type_var().cast(Interner)) - } - GenericParamId::ConstParamId(id) => { - substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)) - } - GenericParamId::LifetimeParamId(_) => { - substs.push(self.table.new_lifetime_var().cast(Interner)) - } + let mut param_to_var = |id| match id { + GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner), + GenericParamId::ConstParamId(id) => { + self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner) } + GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner), + }; + + // Handle everything else as unknown. + for (id, _data) in def_generics.iter().skip(substs.len()) { + substs.push(param_to_var(id)); } assert_eq!(substs.len(), total_len); Substitution::from_iter(Interner, substs) @@ -2143,13 +2149,12 @@ impl InferenceContext<'_> { CallableDefId::FunctionId(f) => { if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container { // construct a TraitRef - let params_len = parameters.len(Interner); let trait_params_len = generics(self.db, trait_.into()).len(); let substs = Substitution::from_iter( Interner, // The generic parameters for the trait come after those for the // function. - ¶meters.as_slice(Interner)[params_len - trait_params_len..], + ¶meters.as_slice(Interner)[..trait_params_len], ); self.push_obligation( TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 7e9cf9f767..461cea4f14 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -105,11 +105,9 @@ impl InferenceContext<'_> { let substs = substs.as_slice(Interner); if let ValueNs::EnumVariantId(_) = value { - let mut it = self_subst - .as_ref() - .map_or(&[][..], |s| s.as_slice(Interner)) + let mut it = substs .iter() - .chain(substs) + .chain(self_subst.as_ref().map_or(&[][..], |s| s.as_slice(Interner))) .cloned(); let builder = TyBuilder::subst_for_def(self.db, generic_def, None); let substs = builder @@ -130,11 +128,11 @@ impl InferenceContext<'_> { let parent_substs = self_subst.or_else(|| { let generics = generics(self.db, generic_def); let parent_params_len = generics.parent_generics()?.len(); - let parent_args = &substs[substs.len() - parent_params_len..]; + let parent_args = &substs[..parent_params_len]; Some(Substitution::from_iter(Interner, parent_args)) }); let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner)); - let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned(); + let mut it = substs.iter().skip(parent_substs_len).cloned(); let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs); let substs = builder .fill(|x| { @@ -261,9 +259,9 @@ impl InferenceContext<'_> { }; if let ItemContainerId::TraitId(trait_) = container { - let param_len = generics(self.db, def).len_self(); + let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self()); let parent_subst = - Substitution::from_iter(Interner, subst.iter(Interner).skip(param_len)); + Substitution::from_iter(Interner, subst.iter(Interner).take(parent_len)); let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst }; self.push_obligation(trait_ref.cast(Interner)); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 2d2ec2866e..57849ff913 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -769,14 +769,8 @@ fn named_associated_type_shorthand_candidates( let impl_id_as_generic_def: GenericDefId = impl_id.into(); if impl_id_as_generic_def != def { - // `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need - // `BoundVar`s from `def`'s point of view. - // FIXME: A `HirDatabase` query may be handy if this process is needed in more - // places. It'd be almost identical as `impl_trait_query` where `resolver` would be - // of `def` instead of `impl_id`. - let starting_idx = generics(db, def).len_self(); let subst = TyBuilder::subst_for_def(db, impl_id, None) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx) + .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) .build(); let trait_ref = subst.apply(trait_ref, Interner); search(trait_ref) @@ -802,16 +796,8 @@ fn named_associated_type_shorthand_candidates( if let GenericDefId::TraitId(trait_id) = param_id.parent() { let trait_generics = generics(db, trait_id.into()); if trait_generics[param_id.local_id()].is_trait_self() { - let def_generics = generics(db, def); - let starting_idx = match def { - GenericDefId::TraitId(_) => 0, - // `def` is an item within trait. We need to substitute `BoundVar`s but - // remember that they are for parent (i.e. trait) generic params so they - // come after our own params. - _ => def_generics.len_self(), - }; let trait_ref = TyBuilder::trait_ref(db, trait_id) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx) + .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) .build(); return search(trait_ref); } @@ -1181,7 +1167,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query( return (GenericDefaults(None), None); } let resolver = def.resolver(db); - let parent_start_idx = generic_params.len_self(); let mut ctx = TyLoweringContext::new(db, &resolver, generic_params.store(), def) .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) @@ -1190,8 +1175,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query( let mut defaults = generic_params .iter_self() .map(|(id, p)| { - let result = - handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params); + let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params); idx += 1; result }) @@ -1199,7 +1183,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query( let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); defaults.extend(generic_params.iter_parents_with_store().map(|((id, p), store)| { ctx.store = store; - let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params); + let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params); idx += 1; result })); @@ -1211,7 +1195,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query( idx: usize, id: GenericParamId, p: GenericParamDataRef<'_>, - parent_start_idx: usize, generic_params: &Generics, ) -> Binders { match p { @@ -1220,7 +1203,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query( // 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) + fallback_bound_vars(ctx.lower_ty(*ty), idx, 0) }); crate::make_binders(ctx.db, generic_params, ty.cast(Interner)) } @@ -1238,7 +1221,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query( }, ); // Each default can only refer to previous parameters, see above. - val = fallback_bound_vars(val, idx, parent_start_idx); + val = fallback_bound_vars(val, idx, 0); make_binders(ctx.db, generic_params, val) } GenericParamDataRef::LifetimeParamData(_) => { diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index bc2d9d9080..a059d9df1c 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -184,14 +184,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { false, None, ); - let len_self = - generics(self.ctx.db, associated_ty.into()).len_self(); let substitution = Substitution::from_iter( Interner, - substitution - .iter(Interner) - .take(len_self) - .chain(trait_ref.substitution.iter(Interner)), + trait_ref.substitution.iter(Interner).chain( + substitution + .iter(Interner) + .skip(trait_ref.substitution.len(Interner)), + ), ); TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty_id: to_assoc_type_id(associated_ty), @@ -250,18 +249,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { let subst = generics.placeholder_subst(self.ctx.db); self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst) } - ParamLoweringMode::Variable => { - let starting_from = match generics.def() { - GenericDefId::ImplId(_) => 0, - // `def` is an item within impl. We need to substitute `BoundVar`s but - // remember that they are for parent (i.e. impl) generic params so they - // come after our own params. - _ => generics.len_self(), - }; - TyBuilder::impl_self_ty(self.ctx.db, impl_id) - .fill_with_bound_vars(self.ctx.in_binders, starting_from) - .build() - } + ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id) + .fill_with_bound_vars(self.ctx.in_binders, 0) + .build(), } } TypeNs::AdtSelfType(adt) => { @@ -512,12 +502,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { // this point (`t.substitution`). let substs = self.substs_from_path_segment(associated_ty.into(), false, None); - let len_self = - crate::generics::generics(self.ctx.db, associated_ty.into()).len_self(); - let substs = Substitution::from_iter( Interner, - substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)), + parent_subst + .iter(Interner) + .chain(substs.iter(Interner).skip(parent_subst.len(Interner))), ); Some( @@ -637,10 +626,10 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { explicit_self_ty: Option, ) -> Substitution { // Order is + // - Parent parameters // - Optional Self parameter // - Lifetime parameters // - Type or Const parameters - // - Parent parameters let def_generics = generics(self.ctx.db, def); let ( parent_params, @@ -654,12 +643,22 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { self_param as usize + type_params + const_params + impl_trait_params + lifetime_params; let total_len = parent_params + item_len; - let mut substs = Vec::new(); + let ty_error = || TyKind::Error.intern(Interner).cast(Interner); + let param_to_err = |id| match id { + GenericParamId::ConstParamId(x) => { + unknown_const_as_generic(self.ctx.db.const_param_ty(x)) + } + GenericParamId::TypeParamId(_) => ty_error(), + GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), + }; + + let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_err).collect(); + + tracing::debug!(?substs, ?parent_params); // we need to iterate the lifetime and type/const params separately as our order of them // differs from the supplied syntax - 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 { @@ -730,13 +729,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { fill_self_param(); } - let param_to_err = |id| match id { - GenericParamId::ConstParamId(x) => { - unknown_const_as_generic(self.ctx.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). @@ -751,13 +743,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty(); if fill_defaults { let defaults = &*self.ctx.db.generic_defaults(def); - let (item, _parent) = defaults.split_at(item_len); - let parent_from = item_len - substs.len(); - let mut rem = + let rem = def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::>(); // Fill in defaults for type/const params - for (idx, default_ty) in item[substs.len()..].iter().enumerate() { + for (idx, default_ty) in defaults[substs.len()..].iter().enumerate() { // each default can depend on the previous parameters let substs_so_far = Substitution::from_iter( Interner, @@ -765,8 +755,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { ); substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); } - // Fill in remaining parent params - substs.extend(rem.drain(parent_from..)); } else { // Fill in remaining def params and parent params substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err)); @@ -818,14 +806,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { false, // this is not relevant Some(super_trait_ref.self_type_parameter(Interner)), ); - let generics = generics(self.ctx.db, associated_ty.into()); - let self_params = generics.len_self(); let substitution = Substitution::from_iter( Interner, - substitution - .iter(Interner) - .take(self_params) - .chain(super_trait_ref.substitution.iter(Interner)), + super_trait_ref.substitution.iter(Interner).chain( + substitution + .iter(Interner) + .skip(super_trait_ref.substitution.len(Interner)), + ), ); let projection_ty = ProjectionTy { associated_ty_id: to_assoc_type_id(associated_ty), diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index d591ea8fe8..52aa355a38 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -655,7 +655,7 @@ pub fn is_dyn_method( let fn_params = fn_subst.len(Interner) - trait_params; let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), - substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)), + substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)), }; let self_ty = trait_ref.self_type_parameter(Interner); if let TyKind::Dyn(d) = self_ty.kind(Interner) { @@ -694,10 +694,9 @@ pub(crate) fn lookup_impl_method_query( return (func, fn_subst); }; let trait_params = db.generic_params(trait_id.into()).len(); - let fn_params = fn_subst.len(Interner) - trait_params; let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), - substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)), + substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)), }; let name = &db.function_signature(func).name; @@ -713,7 +712,7 @@ pub(crate) fn lookup_impl_method_query( impl_fn, Substitution::from_iter( Interner, - fn_subst.iter(Interner).take(fn_params).chain(impl_subst.iter(Interner)), + impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)), ), ) } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index dda7bfb2ba..2fb51acea8 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -4213,7 +4213,7 @@ fn g<'a, T: 'a>(v: impl Trait = &'a T>) { let a = v.get::(); //^ &'a T let a = v.get::<()>(); - //^ Trait::Assoc<(), impl Trait = &'a T>> + //^ Trait::Assoc = &'a T>, ()> } fn h<'a>(v: impl Trait = &'a i32> + Trait = &'a i64>) { let a = v.get::(); @@ -4280,7 +4280,7 @@ where let a = t.get::(); //^ usize let a = t.get::<()>(); - //^ Trait::Assoc<(), T> + //^ Trait::Assoc } "#, diff --git a/crates/hir-ty/src/tls.rs b/crates/hir-ty/src/tls.rs index c8b64f7cbc..f5911e2161 100644 --- a/crates/hir-ty/src/tls.rs +++ b/crates/hir-ty/src/tls.rs @@ -86,8 +86,7 @@ impl DebugContext<'_> { } write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?; - let proj_params_count = projection_ty.substitution.len(Interner) - trait_params.len(); - let proj_params = &projection_ty.substitution.as_slice(Interner)[..proj_params_count]; + let proj_params = &projection_ty.substitution.as_slice(Interner)[trait_params.len()..]; if !proj_params.is_empty() { write!( fmt, diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 3efd9a560f..c95c0ef55a 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -230,8 +230,8 @@ pub(super) fn associated_type_by_name_including_super_traits( } /// It is a bit different from the rustc equivalent. Currently it stores: -/// - 0: the function signature, encoded as a function pointer type -/// - 1..n: generics of the parent +/// - 0..n-1: generics of the parent +/// - n: the function signature, encoded as a function pointer type /// /// and it doesn't store the closure types and fields. /// @@ -242,7 +242,7 @@ pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution); impl<'a> ClosureSubst<'a> { pub(crate) fn parent_subst(&self) -> &'a [GenericArg] { match self.0.as_slice(Interner) { - [_, x @ ..] => x, + [x @ .., _] => x, _ => { never!("Closure missing parameter"); &[] @@ -252,7 +252,7 @@ impl<'a> ClosureSubst<'a> { pub(crate) fn sig_ty(&self) -> &'a Ty { match self.0.as_slice(Interner) { - [x, ..] => x.assert_ty_ref(Interner), + [.., x] => x.assert_ty_ref(Interner), _ => { unreachable!("Closure missing sig_ty parameter"); } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4414c79f8b..578e9e38be 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3774,24 +3774,25 @@ impl GenericSubstitution { TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), TypeOrConstParamData::ConstParamData(_) => None, }); - // The `Substitution` is first self then container, we want the reverse order. - let subst_type_params = self.subst.type_parameters(Interner).collect::>(); - let mut self_params = subst_type_params + let parent_len = self.subst.len(Interner) + - generics + .iter_type_or_consts() + .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..))) + .count(); + let container_params = self.subst.as_slice(Interner)[..parent_len] .iter() - .zip(type_params) - .filter_map(|(ty, name)| { - Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() })) - }) - .collect::>(); - let mut container_params = subst_type_params[self_params.len()..] + .filter_map(|param| param.ty(Interner).cloned()) + .zip(container_type_params.into_iter().flatten()); + let self_params = self.subst.as_slice(Interner)[parent_len..] .iter() - .zip(container_type_params.into_iter().flatten()) - .filter_map(|(ty, name)| { - Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() })) - }) - .collect::>(); - container_params.append(&mut self_params); + .filter_map(|param| param.ty(Interner).cloned()) + .zip(type_params); container_params + .chain(self_params) + .filter_map(|(ty, name)| { + Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() })) + }) + .collect() } }