fix: Fix implicit ty args being lowered where they shouldn't

This commit is contained in:
Lukas Wirth 2024-05-02 11:53:53 +02:00
parent 9ce7ab6fa9
commit f190ce61b7
4 changed files with 116 additions and 120 deletions

View File

@ -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)>,

View File

@ -662,7 +662,7 @@ fn lower_generic_params(
let attrs = RawAttrs::new(self.db.upcast(), &param, self.body_ctx.span_map()); let attrs = RawAttrs::new(self.db.upcast(), &param, 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 {

View File

@ -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)
}
_ => None,
}) })
.nth(idx as usize) .nth(idx as usize)
.map_or(TyKind::Error, |(id, _)| { .map_or(TyKind::Error, |id| {
if let GenericParamId::TypeParamId(id) = id {
TyKind::Placeholder(to_placeholder_idx(self.db, id.into())) TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
} else {
// we just filtered them out
unreachable!("Unexpected lifetime or const argument");
}
}); });
param.intern(Interner) kind.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,30 +1142,22 @@ 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(_)
| ImplTraitLoweringState::Variable(_)
) {
// Find the generic index for the target of our `bound` // Find the generic index for the target of our `bound`
let target_param_idx = self let target_param_idx = self
.resolver .resolver
@ -1185,7 +1169,7 @@ fn assoc_type_bindings_from_type_bound(
} if b == bound => Some(idx), } if b == bound => Some(idx),
_ => None, _ => None,
}); });
if let Some(target_param_idx) = target_param_idx { let ty = if let Some(target_param_idx) = target_param_idx {
let mut counter = 0; let mut counter = 0;
let generics = self.generics().expect("generics in scope"); let generics = self.generics().expect("generics in scope");
for (idx, data) in generics.params.type_or_consts.iter() { for (idx, data) in generics.params.type_or_consts.iter() {
@ -1214,20 +1198,21 @@ fn assoc_type_bindings_from_type_bound(
ImplTraitLoweringState::Param(Cell::new(counter)); ImplTraitLoweringState::Param(Cell::new(counter));
} }
ImplTraitLoweringState::Variable(_) => { ImplTraitLoweringState::Variable(_) => {
ext.impl_trait_mode = ImplTraitLoweringState::Variable( ext.impl_trait_mode =
Cell::new(counter), ImplTraitLoweringState::Variable(Cell::new(counter));
);
} }
_ => unreachable!(), _ => unreachable!(),
} }
break 'ty ext.lower_ty(type_ref); ext.lower_ty(type_ref)
} } else {
}
self.lower_ty(type_ref) self.lower_ty(type_ref)
}; };
let alias_eq = let alias_eq =
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); 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 {

View File

@ -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,
{}
"#,
);
}