}
fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
- let (def, res) = match (self.resolver.generic_def(), res) {
- (Some(def), Some(res)) => (def, res),
- _ => return TyKind::Error.intern(Interner),
+ let Some((def, res)) = self.resolver.generic_def().zip(res) else {
+ return TyKind::Error.intern(Interner);
};
let ty = named_associated_type_shorthand_candidates(
self.db,
return None;
}
+ let parent_subst = t.substitution.clone();
+ let parent_subst = match self.type_param_mode {
+ ParamLoweringMode::Placeholder => {
+ // if we're lowering to placeholders, we have to put them in now.
+ let generics = generics(self.db.upcast(), def);
+ let s = generics.placeholder_subst(self.db);
+ s.apply(parent_subst, Interner)
+ }
+ ParamLoweringMode::Variable => {
+ // We need to shift in the bound vars, since
+ // `named_associated_type_shorthand_candidates` does not do that.
+ parent_subst.shifted_in_from(Interner, self.in_binders)
+ }
+ };
+
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
// generic params. It's inefficient to splice the `Substitution`s, so we may want
// that method to optionally take parent `Substitution` as we already know them at
let substs = Substitution::from_iter(
Interner,
- substs.iter(Interner).take(len_self).chain(t.substitution.iter(Interner)),
+ substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)),
);
- let substs = match self.type_param_mode {
- ParamLoweringMode::Placeholder => {
- // if we're lowering to placeholders, we have to put
- // them in now
- let generics = generics(self.db.upcast(), def);
- let s = generics.placeholder_subst(self.db);
- s.apply(substs, Interner)
- }
- ParamLoweringMode::Variable => substs,
- };
- // We need to shift in the bound vars, since
- // associated_type_shorthand_candidates does not do that
- let substs = substs.shifted_in_from(Interner, self.in_binders);
Some(
TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(associated_ty),
|_, c, ty| {
const_or_path_to_chalk(
self.db,
- &self.resolver,
+ self.resolver,
ty,
c,
self.type_param_mode,
db: &dyn HirDatabase,
def: GenericDefId,
res: TypeNs,
- cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
+ mut cb: impl FnMut(&Name, TypeAliasId) -> Option<R>,
) -> Option<R> {
- named_associated_type_shorthand_candidates(db, def, res, None, cb)
+ named_associated_type_shorthand_candidates(db, def, res, None, |name, _, id| cb(name, id))
}
fn named_associated_type_shorthand_candidates<R>(
def: GenericDefId,
res: TypeNs,
assoc_name: Option<Name>,
+ // Do NOT let `cb` touch `TraitRef` outside of `TyLoweringContext`. Its substitution contains
+ // free `BoundVar`s that need to be shifted and only `TyLoweringContext` knows how to do that
+ // properly (see `TyLoweringContext::select_associated_type()`).
mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
) -> Option<R> {
let mut search = |t| {
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
let _cx = stdx::panic_context::enter(format!(
- "impl_self_ty_query({:?} -> {:?} -> {:?})",
- impl_id, impl_loc, impl_data
+ "impl_self_ty_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
));
let generics = generics(db.upcast(), impl_id.into());
let ctx =
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
let _cx = stdx::panic_context::enter(format!(
- "impl_trait_query({:?} -> {:?} -> {:?})",
- impl_id, impl_loc, impl_data
+ "impl_trait_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
));
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
let ctx_ret = TyLoweringContext::new(db, &resolver)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
.with_type_param_mode(ParamLoweringMode::Variable);
- let _ret = (&ctx_ret).lower_ty(&data.ret_type);
+ let _ret = ctx_ret.lower_ty(&data.ret_type);
let generics = generics(db.upcast(), def.into());
let return_type_impl_traits =
ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() };
if bound.index_if_innermost().map_or(true, is_allowed) {
bound.shifted_in_from(binders).to_const(Interner, ty)
} else {
- unknown_const(ty.clone())
+ unknown_const(ty)
}
},
)