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)
}) }
.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 {

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