about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2025-08-24 08:49:40 +0300
committerChayim Refael Friedman <chayimfr@gmail.com>2025-08-24 08:49:40 +0300
commit31245cabecfc21c837745ec6253d63d5fc9ac75f (patch)
treeab49be0356f796f19a490ff94c8ad810dd80aca6
parentcf358c09cebfe3e1c0d7145242396f6066033fad (diff)
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).
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs68
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs26
4 files changed, 54 insertions, 43 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs
index 48f5e73f256..a3ba8eb8345 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs
index cedc203f7f5..1db02e9eb61 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index 966433369aa..6a3f2286215 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
new file mode 100644
index 00000000000..059f4ad32a5
--- /dev/null
+++ b/src/tools/rust-analyzer/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 ()>
+        "#]],
+    );
+}