fix: Fix implicit ty args being lowered where they shouldn't
This commit is contained in:
parent
9ce7ab6fa9
commit
f190ce61b7
@ -377,7 +377,7 @@ fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<Interned<TypeBound>>>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fill_implicit_impl_trait_args(
|
fn fill_implicit_impl_trait_args(
|
||||||
&mut self,
|
&mut self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>,
|
exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>,
|
||||||
|
@ -662,7 +662,7 @@ fn lower_generic_params(
|
|||||||
let attrs = RawAttrs::new(self.db.upcast(), ¶m, self.body_ctx.span_map());
|
let attrs = RawAttrs::new(self.db.upcast(), ¶m, self.body_ctx.span_map());
|
||||||
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
||||||
};
|
};
|
||||||
|
self.body_ctx.take_impl_traits_bounds();
|
||||||
let mut generics = GenericParamsCollector::default();
|
let mut generics = GenericParamsCollector::default();
|
||||||
|
|
||||||
if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
|
if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
|
||||||
|
@ -345,51 +345,43 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
|||||||
}
|
}
|
||||||
ImplTraitLoweringState::Param(counter) => {
|
ImplTraitLoweringState::Param(counter) => {
|
||||||
let idx = counter.get();
|
let idx = counter.get();
|
||||||
// FIXME we're probably doing something wrong here
|
counter.set(idx + 1);
|
||||||
counter.set(idx + count_impl_traits(type_ref) as u16);
|
let kind = self
|
||||||
if let Some(generics) = self.generics() {
|
.generics()
|
||||||
let param = generics
|
.expect("param impl trait lowering must be in a generic def")
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, data)| {
|
.filter_map(|(id, data)| match (id, data) {
|
||||||
matches!(
|
(
|
||||||
data,
|
GenericParamId::TypeParamId(id),
|
||||||
GenericParamDataRef::TypeParamData(data)
|
GenericParamDataRef::TypeParamData(data),
|
||||||
if data.provenance == TypeParamProvenance::ArgumentImplTrait
|
) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
|
||||||
)
|
Some(id)
|
||||||
})
|
}
|
||||||
.nth(idx as usize)
|
_ => None,
|
||||||
.map_or(TyKind::Error, |(id, _)| {
|
})
|
||||||
if let GenericParamId::TypeParamId(id) = id {
|
.nth(idx as usize)
|
||||||
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
.map_or(TyKind::Error, |id| {
|
||||||
} else {
|
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
||||||
// we just filtered them out
|
});
|
||||||
unreachable!("Unexpected lifetime or const argument");
|
kind.intern(Interner)
|
||||||
}
|
|
||||||
});
|
|
||||||
param.intern(Interner)
|
|
||||||
} else {
|
|
||||||
TyKind::Error.intern(Interner)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImplTraitLoweringState::Variable(counter) => {
|
ImplTraitLoweringState::Variable(counter) => {
|
||||||
let idx = counter.get();
|
let idx = counter.get();
|
||||||
// FIXME we're probably doing something wrong here
|
counter.set(idx + 1);
|
||||||
counter.set(idx + count_impl_traits(type_ref) as u16);
|
|
||||||
let (
|
let (
|
||||||
_parent_params,
|
_parent_params,
|
||||||
self_params,
|
self_params,
|
||||||
list_params,
|
type_params,
|
||||||
const_params,
|
const_params,
|
||||||
_impl_trait_params,
|
_impl_trait_params,
|
||||||
_lifetime_params,
|
_lifetime_params,
|
||||||
) = if let Some(generics) = self.generics() {
|
) = self
|
||||||
generics.provenance_split()
|
.generics()
|
||||||
} else {
|
.expect("variable impl trait lowering must be in a generic def")
|
||||||
(0, 0, 0, 0, 0, 0)
|
.provenance_split();
|
||||||
};
|
|
||||||
TyKind::BoundVar(BoundVar::new(
|
TyKind::BoundVar(BoundVar::new(
|
||||||
self.in_binders,
|
self.in_binders,
|
||||||
idx as usize + self_params + list_params + const_params,
|
idx as usize + self_params + type_params + const_params,
|
||||||
))
|
))
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
}
|
}
|
||||||
@ -1150,84 +1142,77 @@ fn assoc_type_bindings_from_type_bound(
|
|||||||
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
||||||
);
|
);
|
||||||
if let Some(type_ref) = &binding.type_ref {
|
if let Some(type_ref) = &binding.type_ref {
|
||||||
if let (
|
match (type_ref, &self.impl_trait_mode) {
|
||||||
TypeRef::ImplTrait(bounds),
|
(TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
|
||||||
ImplTraitLoweringState::Param(_)
|
(
|
||||||
| ImplTraitLoweringState::Variable(_)
|
_,
|
||||||
| ImplTraitLoweringState::Disallowed,
|
ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
|
||||||
) = (type_ref, &self.impl_trait_mode)
|
) => {
|
||||||
{
|
let ty = self.lower_ty(type_ref);
|
||||||
for bound in bounds {
|
let alias_eq =
|
||||||
predicates.extend(
|
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
||||||
self.lower_type_bound(
|
predicates
|
||||||
bound,
|
.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
||||||
TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
|
|
||||||
.intern(Interner),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
(
|
||||||
let ty = 'ty: {
|
_,
|
||||||
if matches!(
|
ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_),
|
||||||
self.impl_trait_mode,
|
) => {
|
||||||
ImplTraitLoweringState::Param(_)
|
// Find the generic index for the target of our `bound`
|
||||||
| ImplTraitLoweringState::Variable(_)
|
let target_param_idx = self
|
||||||
) {
|
.resolver
|
||||||
// Find the generic index for the target of our `bound`
|
.where_predicates_in_scope()
|
||||||
let target_param_idx = self
|
.find_map(|(p, _)| match p {
|
||||||
.resolver
|
WherePredicate::TypeBound {
|
||||||
.where_predicates_in_scope()
|
target: WherePredicateTypeTarget::TypeOrConstParam(idx),
|
||||||
.find_map(|(p, _)| match p {
|
bound: b,
|
||||||
WherePredicate::TypeBound {
|
} if b == bound => Some(idx),
|
||||||
target: WherePredicateTypeTarget::TypeOrConstParam(idx),
|
_ => None,
|
||||||
bound: b,
|
});
|
||||||
} if b == bound => Some(idx),
|
let ty = if let Some(target_param_idx) = target_param_idx {
|
||||||
_ => None,
|
let mut counter = 0;
|
||||||
});
|
let generics = self.generics().expect("generics in scope");
|
||||||
if let Some(target_param_idx) = target_param_idx {
|
for (idx, data) in generics.params.type_or_consts.iter() {
|
||||||
let mut counter = 0;
|
// Count the number of `impl Trait` things that appear before
|
||||||
let generics = self.generics().expect("generics in scope");
|
// the target of our `bound`.
|
||||||
for (idx, data) in generics.params.type_or_consts.iter() {
|
// Our counter within `impl_trait_mode` should be that number
|
||||||
// Count the number of `impl Trait` things that appear before
|
// to properly lower each types within `type_ref`
|
||||||
// the target of our `bound`.
|
if data.type_param().is_some_and(|p| {
|
||||||
// Our counter within `impl_trait_mode` should be that number
|
p.provenance == TypeParamProvenance::ArgumentImplTrait
|
||||||
// to properly lower each types within `type_ref`
|
}) {
|
||||||
if data.type_param().is_some_and(|p| {
|
counter += 1;
|
||||||
p.provenance == TypeParamProvenance::ArgumentImplTrait
|
|
||||||
}) {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
if idx == *target_param_idx {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let mut ext = TyLoweringContext::new_maybe_unowned(
|
if idx == *target_param_idx {
|
||||||
self.db,
|
break;
|
||||||
self.resolver,
|
|
||||||
self.owner,
|
|
||||||
)
|
|
||||||
.with_type_param_mode(self.type_param_mode);
|
|
||||||
match &self.impl_trait_mode {
|
|
||||||
ImplTraitLoweringState::Param(_) => {
|
|
||||||
ext.impl_trait_mode =
|
|
||||||
ImplTraitLoweringState::Param(Cell::new(counter));
|
|
||||||
}
|
|
||||||
ImplTraitLoweringState::Variable(_) => {
|
|
||||||
ext.impl_trait_mode = ImplTraitLoweringState::Variable(
|
|
||||||
Cell::new(counter),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
break 'ty ext.lower_ty(type_ref);
|
|
||||||
}
|
}
|
||||||
}
|
let mut ext = TyLoweringContext::new_maybe_unowned(
|
||||||
self.lower_ty(type_ref)
|
self.db,
|
||||||
};
|
self.resolver,
|
||||||
let alias_eq =
|
self.owner,
|
||||||
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
)
|
||||||
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
.with_type_param_mode(self.type_param_mode);
|
||||||
|
match &self.impl_trait_mode {
|
||||||
|
ImplTraitLoweringState::Param(_) => {
|
||||||
|
ext.impl_trait_mode =
|
||||||
|
ImplTraitLoweringState::Param(Cell::new(counter));
|
||||||
|
}
|
||||||
|
ImplTraitLoweringState::Variable(_) => {
|
||||||
|
ext.impl_trait_mode =
|
||||||
|
ImplTraitLoweringState::Variable(Cell::new(counter));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
ext.lower_ty(type_ref)
|
||||||
|
} else {
|
||||||
|
self.lower_ty(type_ref)
|
||||||
|
};
|
||||||
|
|
||||||
|
let alias_eq =
|
||||||
|
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
||||||
|
predicates
|
||||||
|
.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for bound in binding.bounds.iter() {
|
for bound in binding.bounds.iter() {
|
||||||
@ -1394,16 +1379,6 @@ pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
|
||||||
let mut count = 0;
|
|
||||||
type_ref.walk(&mut |type_ref| {
|
|
||||||
if matches!(type_ref, TypeRef::ImplTrait(_)) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
count
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build the signature of a callable item (function, struct or enum variant).
|
/// Build the signature of a callable item (function, struct or enum variant).
|
||||||
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
|
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
|
||||||
match def {
|
match def {
|
||||||
|
@ -1975,3 +1975,24 @@ impl<#[cfg(feature = "a-feature")] A> Bar for (){}
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_anon_generics_and_where_bounds_17173() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
//- minicore: sized
|
||||||
|
pub trait Lookup {
|
||||||
|
type Data;
|
||||||
|
fn lookup(&self) -> Self::Data;
|
||||||
|
}
|
||||||
|
pub trait ItemTreeLoc {
|
||||||
|
type Id;
|
||||||
|
}
|
||||||
|
fn id_to_generics(id: impl Lookup<Data = impl ItemTreeLoc<Id = ()>>)
|
||||||
|
//^^ impl Lookup<Data = impl ItemTreeLoc<Id = ()>>
|
||||||
|
where
|
||||||
|
(): Sized,
|
||||||
|
{}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user