Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/generics.rs2
-rw-r--r--crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--crates/hir-ty/src/lower.rs211
-rw-r--r--crates/hir-ty/src/tests/regression.rs21
4 files changed, 116 insertions, 120 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 3a277ecb90..10a1d65bb9 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -377,7 +377,7 @@ impl GenericParamsCollector {
}
}
- pub(crate) fn fill_implicit_impl_trait_args(
+ fn fill_implicit_impl_trait_args(
&mut self,
db: &dyn DefDatabase,
exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>,
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 6aa5a63d62..199b8daa37 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -662,7 +662,7 @@ impl<'a> Ctx<'a> {
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());
};
-
+ self.body_ctx.take_impl_traits_bounds();
let mut generics = GenericParamsCollector::default();
if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 706b034821..04e2ded05a 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -345,51 +345,43 @@ impl<'a> TyLoweringContext<'a> {
}
ImplTraitLoweringState::Param(counter) => {
let idx = counter.get();
- // FIXME we're probably doing something wrong here
- counter.set(idx + count_impl_traits(type_ref) as u16);
- if let Some(generics) = self.generics() {
- let param = generics
- .iter()
- .filter(|(_, data)| {
- matches!(
- data,
- GenericParamDataRef::TypeParamData(data)
- if data.provenance == TypeParamProvenance::ArgumentImplTrait
- )
- })
- .nth(idx as usize)
- .map_or(TyKind::Error, |(id, _)| {
- if let GenericParamId::TypeParamId(id) = id {
- TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
- } else {
- // we just filtered them out
- unreachable!("Unexpected lifetime or const argument");
- }
- });
- param.intern(Interner)
- } else {
- TyKind::Error.intern(Interner)
- }
+ counter.set(idx + 1);
+ let kind = self
+ .generics()
+ .expect("param impl trait lowering must be in a generic def")
+ .iter()
+ .filter_map(|(id, data)| match (id, data) {
+ (
+ GenericParamId::TypeParamId(id),
+ GenericParamDataRef::TypeParamData(data),
+ ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
+ Some(id)
+ }
+ _ => None,
+ })
+ .nth(idx as usize)
+ .map_or(TyKind::Error, |id| {
+ TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+ });
+ kind.intern(Interner)
}
ImplTraitLoweringState::Variable(counter) => {
let idx = counter.get();
- // FIXME we're probably doing something wrong here
- counter.set(idx + count_impl_traits(type_ref) as u16);
+ counter.set(idx + 1);
let (
_parent_params,
self_params,
- list_params,
+ type_params,
const_params,
_impl_trait_params,
_lifetime_params,
- ) = if let Some(generics) = self.generics() {
- generics.provenance_split()
- } else {
- (0, 0, 0, 0, 0, 0)
- };
+ ) = self
+ .generics()
+ .expect("variable impl trait lowering must be in a generic def")
+ .provenance_split();
TyKind::BoundVar(BoundVar::new(
self.in_binders,
- idx as usize + self_params + list_params + const_params,
+ idx as usize + self_params + type_params + const_params,
))
.intern(Interner)
}
@@ -1150,84 +1142,77 @@ impl<'a> TyLoweringContext<'a> {
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
);
if let Some(type_ref) = &binding.type_ref {
- if let (
- TypeRef::ImplTrait(bounds),
- ImplTraitLoweringState::Param(_)
- | ImplTraitLoweringState::Variable(_)
- | ImplTraitLoweringState::Disallowed,
- ) = (type_ref, &self.impl_trait_mode)
- {
- for bound in bounds {
- predicates.extend(
- self.lower_type_bound(
- bound,
- TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
- .intern(Interner),
- false,
- ),
- );
+ match (type_ref, &self.impl_trait_mode) {
+ (TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
+ (
+ _,
+ ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
+ ) => {
+ let ty = 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)));
}
- } else {
- let ty = 'ty: {
- if matches!(
- self.impl_trait_mode,
- ImplTraitLoweringState::Param(_)
- | ImplTraitLoweringState::Variable(_)
- ) {
- // Find the generic index for the target of our `bound`
- let target_param_idx = self
- .resolver
- .where_predicates_in_scope()
- .find_map(|(p, _)| match p {
- WherePredicate::TypeBound {
- target: WherePredicateTypeTarget::TypeOrConstParam(idx),
- bound: b,
- } if b == bound => Some(idx),
- _ => None,
- });
- if let Some(target_param_idx) = target_param_idx {
- let mut counter = 0;
- let generics = self.generics().expect("generics in scope");
- for (idx, data) in generics.params.type_or_consts.iter() {
- // Count the number of `impl Trait` things that appear before
- // the target of our `bound`.
- // Our counter within `impl_trait_mode` should be that number
- // to properly lower each types within `type_ref`
- if data.type_param().is_some_and(|p| {
- p.provenance == TypeParamProvenance::ArgumentImplTrait
- }) {
- counter += 1;
- }
- if idx == *target_param_idx {
- break;
- }
+ (
+ _,
+ ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_),
+ ) => {
+ // Find the generic index for the target of our `bound`
+ let target_param_idx = self
+ .resolver
+ .where_predicates_in_scope()
+ .find_map(|(p, _)| match p {
+ WherePredicate::TypeBound {
+ target: WherePredicateTypeTarget::TypeOrConstParam(idx),
+ bound: b,
+ } if b == bound => Some(idx),
+ _ => None,
+ });
+ let ty = if let Some(target_param_idx) = target_param_idx {
+ let mut counter = 0;
+ let generics = self.generics().expect("generics in scope");
+ for (idx, data) in generics.params.type_or_consts.iter() {
+ // Count the number of `impl Trait` things that appear before
+ // the target of our `bound`.
+ // Our counter within `impl_trait_mode` should be that number
+ // to properly lower each types within `type_ref`
+ if data.type_param().is_some_and(|p| {
+ p.provenance == TypeParamProvenance::ArgumentImplTrait
+ }) {
+ counter += 1;
}
- let mut ext = TyLoweringContext::new_maybe_unowned(
- self.db,
- 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!(),
+ if idx == *target_param_idx {
+ break;
}
- break 'ty ext.lower_ty(type_ref);
}
- }
- 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)));
+ let mut ext = TyLoweringContext::new_maybe_unowned(
+ self.db,
+ 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!(),
+ }
+ 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() {
@@ -1394,16 +1379,6 @@ impl<'a> TyLoweringContext<'a> {
}
}
-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).
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
match def {
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 69c7a81548..f80d539498 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -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,
+{}
+"#,
+ );
+}