Unnamed repository; edit this file 'description' to name the repository.
Fix opaque generics
The parent generics were incorrectly not considered for TAIT. I'm not convinced we should follow rustc here, also there are items (opaques) with more than 1 parent (opaque -> fn/type alias -> impl/trait) and I'm not sure we properly account for that in all places, but for now I left it as-is. Also fix a bug where lifetimes' indices were incorrect when there is a self param (they started from 0 instead of 1).
Chayim Refael Friedman 8 months ago
parent e6cd085 · commit 03173a7
-rw-r--r--crates/hir-ty/src/next_solver/generics.rs68
-rw-r--r--crates/hir-ty/src/next_solver/util.rs1
-rw-r--r--crates/hir-ty/src/tests/regression.rs2
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs26
4 files changed, 54 insertions, 43 deletions
diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs
index 48f5e73f25..a3ba8eb834 100644
--- a/crates/hir-ty/src/next_solver/generics.rs
+++ b/crates/hir-ty/src/next_solver/generics.rs
@@ -12,7 +12,7 @@ use hir_def::{
},
};
use hir_expand::name::Name;
-use intern::Symbol;
+use intern::{Symbol, sym};
use la_arena::Arena;
use rustc_type_ir::inherent::Ty as _;
use triomphe::Arc;
@@ -24,18 +24,13 @@ use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, Solver
use super::{DbInterner, GenericArg};
pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
- let mk_lt = |(index, (_, lt)): (usize, (_, &LifetimeParamData))| {
+ let mk_lt = |index, lt: &LifetimeParamData| {
let name = lt.name.symbol().clone();
- let index = index as u32;
let kind = GenericParamDefKind::Lifetime;
GenericParamDef { name, index, kind }
};
- let mk_ty = |len_lt, (index, p): (usize, &TypeOrConstParamData)| {
- let name = p
- .name()
- .map(|n| n.symbol().clone())
- .unwrap_or_else(|| Name::missing().symbol().clone());
- let index = (len_lt + index) as u32;
+ let mk_ty = |index, p: &TypeOrConstParamData| {
+ let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME);
let kind = match p {
TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type,
TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const,
@@ -43,33 +38,25 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
GenericParamDef { name, index, kind }
};
let own_params_for_generic_params = |params: &GenericParams| {
- if params.trait_self_param().is_some() {
- let len_lt = params.len_lifetimes() + 1;
- params
- .iter_type_or_consts()
- .take(1)
- .enumerate()
- .map(|t| mk_ty(0, (t.0, t.1.1)))
- .chain(params.iter_lt().enumerate().map(mk_lt))
- .chain(
- params
- .iter_type_or_consts()
- .skip(1)
- .enumerate()
- .map(|t| mk_ty(len_lt, (t.0, t.1.1))),
- )
- .collect()
- } else {
- let len_lt = params.len_lifetimes();
- params
- .iter_lt()
- .enumerate()
- .map(mk_lt)
- .chain(
- params.iter_type_or_consts().enumerate().map(|t| mk_ty(len_lt, (t.0, t.1.1))),
- )
- .collect()
+ let mut result = Vec::with_capacity(params.len());
+ let mut type_and_consts = params.iter_type_or_consts();
+ let mut index = 0;
+ if let Some(self_param) = params.trait_self_param() {
+ result.push(mk_ty(0, &params[self_param]));
+ type_and_consts.next();
+ index += 1;
}
+ result.extend(params.iter_lt().map(|(_, data)| {
+ let lt = mk_lt(index, data);
+ index += 1;
+ lt
+ }));
+ result.extend(type_and_consts.map(|(_, data)| {
+ let ty = mk_ty(index, data);
+ index += 1;
+ ty
+ }));
+ result
};
let (parent, own_params) = match (def.try_into(), def) {
@@ -82,12 +69,9 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
// The opaque type itself does not have generics - only the parent function
(Some(GenericDefId::FunctionId(function_id)), vec![])
}
- crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => (
- None,
- own_params_for_generic_params(
- &db.generic_params(GenericDefId::TypeAliasId(type_alias_id)),
- ),
- ),
+ crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => {
+ (Some(type_alias_id.into()), Vec::new())
+ }
crate::ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
let param = TypeOrConstParamData::TypeParamData(TypeParamData {
name: None,
@@ -95,7 +79,7 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
provenance: TypeParamProvenance::TypeParamList,
});
// Yes, there is a parent but we don't include it in the generics
- (None, vec![mk_ty(0, (0, &param))])
+ (None, vec![mk_ty(0, &param)])
}
}
}
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index cedc203f7f..1db02e9eb6 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -685,7 +685,6 @@ pub fn explicit_item_bounds<'db>(
LifetimeElisionKind::AnonymousReportError,
);
- let trait_args = GenericArgs::identity_for_item(interner, trait_.into());
let item_args = GenericArgs::identity_for_item(interner, def_id);
let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 966433369a..6a3f228621 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1,3 +1,5 @@
+mod new_solver;
+
use expect_test::expect;
use super::{check_infer, check_no_mismatches, check_types};
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
new file mode 100644
index 0000000000..059f4ad32a
--- /dev/null
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -0,0 +1,26 @@
+use expect_test::expect;
+
+use super::check_infer;
+
+#[test]
+fn opaque_generics() {
+ check_infer(
+ r#"
+//- minicore: iterator
+pub struct Grid {}
+
+impl<'a> IntoIterator for &'a Grid {
+ type Item = &'a ();
+
+ type IntoIter = impl Iterator<Item = &'a ()>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ }
+}
+ "#,
+ expect![[r#"
+ 150..154 'self': &'a Grid
+ 174..181 '{ }': impl Iterator<Item = &'a ()>
+ "#]],
+ );
+}