about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-06-21 17:55:16 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-06-21 17:55:16 +0200
commit3a66230a4496123e55cc05fe4345b3120858e67b (patch)
tree56741385ea0aaf02ec5f838ecfc1b25c73f1b0aa
parentc133c649a00a82b2709e7f7c0ce27f704b4f30b3 (diff)
downloadrust-3a66230a4496123e55cc05fe4345b3120858e67b.tar.gz
rust-3a66230a4496123e55cc05fe4345b3120858e67b.zip
There can only be one self param
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs66
5 files changed, 61 insertions, 66 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index acead9dc17c..a7ce69113fb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -11,7 +11,7 @@ use hir_expand::{
     ExpandResult,
 };
 use intern::Interned;
-use la_arena::Arena;
+use la_arena::{Arena, RawIdx};
 use once_cell::unsync::Lazy;
 use stdx::impl_from;
 use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
@@ -28,6 +28,9 @@ use crate::{
     LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
 };
 
+const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
+    LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
+
 /// Data about a generic type parameter (to a function, struct, impl, ...).
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct TypeParamData {
@@ -606,16 +609,17 @@ impl GenericParams {
     }
 
     pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
-        self.type_or_consts.iter().find_map(|(id, p)| {
-            matches!(
-                p,
-                TypeOrConstParamData::TypeParamData(TypeParamData {
-                    provenance: TypeParamProvenance::TraitSelf,
-                    ..
-                })
-            )
-            .then(|| id)
-        })
+        if self.type_or_consts.is_empty() {
+            return None;
+        }
+        matches!(
+            self.type_or_consts[SELF_PARAM_ID_IN_SELF],
+            TypeOrConstParamData::TypeParamData(TypeParamData {
+                provenance: TypeParamProvenance::TraitSelf,
+                ..
+            })
+        )
+        .then(|| SELF_PARAM_ID_IN_SELF)
     }
 
     pub fn find_lifetime_by_name(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index d6a65db14f2..66b5398b88e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -989,7 +989,7 @@ impl HirDisplay for Ty {
 
                 if parameters.len(Interner) > 0 {
                     let generics = generics(db.upcast(), def.into());
-                    let (parent_len, self_, type_, const_, impl_, lifetime) =
+                    let (parent_len, self_param, type_, const_, impl_, lifetime) =
                         generics.provenance_split();
                     let parameters = parameters.as_slice(Interner);
                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
@@ -997,7 +997,7 @@ impl HirDisplay for Ty {
                         // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
                         // parent's params (those from enclosing impl or trait, if any).
                         let (fn_params, other) =
-                            parameters.split_at(self_ + type_ + const_ + lifetime);
+                            parameters.split_at(self_param as usize + type_ + const_ + lifetime);
                         let (_impl, parent_params) = other.split_at(impl_);
                         debug_assert_eq!(parent_params.len(), parent_len);
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index 8a421b262e2..21bed9d3dae 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -53,6 +53,10 @@ impl Generics {
         self.iter().map(|(id, _)| id)
     }
 
+    pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+        self.iter_self().map(|(id, _)| id)
+    }
+
     pub(crate) fn iter_self_type_or_consts(
         &self,
     ) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
@@ -99,8 +103,8 @@ impl Generics {
     }
 
     /// (parent total, self param, type params, const params, impl trait list, lifetimes)
-    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
-        let mut self_params = 0;
+    pub(crate) fn provenance_split(&self) -> (usize, bool, usize, usize, usize, usize) {
+        let mut self_param = false;
         let mut type_params = 0;
         let mut impl_trait_params = 0;
         let mut const_params = 0;
@@ -108,7 +112,7 @@ impl Generics {
         self.params.iter_type_or_consts().for_each(|(_, data)| match data {
             TypeOrConstParamData::TypeParamData(p) => match p.provenance {
                 TypeParamProvenance::TypeParamList => type_params += 1,
-                TypeParamProvenance::TraitSelf => self_params += 1,
+                TypeParamProvenance::TraitSelf => self_param |= true,
                 TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
             },
             TypeOrConstParamData::ConstParamData(_) => const_params += 1,
@@ -117,7 +121,7 @@ impl Generics {
         self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
 
         let parent_len = self.parent_generics().map_or(0, Generics::len);
-        (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
+        (parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params)
     }
 
     pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 5786d4d3821..95f28531acf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -1830,13 +1830,13 @@ impl InferenceContext<'_> {
     ) -> Substitution {
         let (
             parent_params,
-            self_params,
+            has_self_param,
             type_params,
             const_params,
             impl_trait_params,
             lifetime_params,
         ) = def_generics.provenance_split();
-        assert_eq!(self_params, 0); // method shouldn't have another Self param
+        assert!(!has_self_param); // method shouldn't have another Self param
         let total_len =
             parent_params + type_params + const_params + impl_trait_params + lifetime_params;
         let mut substs = Vec::with_capacity(total_len);
@@ -1844,13 +1844,11 @@ impl InferenceContext<'_> {
         // handle provided arguments
         if let Some(generic_args) = generic_args {
             // if args are provided, it should be all of them, but we can't rely on that
-            for (arg, kind_id) in generic_args
-                .args
-                .iter()
-                .take(type_params + const_params + lifetime_params)
-                .zip(def_generics.iter_id())
+            let self_params = type_params + const_params + lifetime_params;
+            for (arg, kind_id) in
+                generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params)
             {
-                if let Some(g) = generic_arg_to_chalk(
+                let arg = generic_arg_to_chalk(
                     self.db,
                     kind_id,
                     arg,
@@ -1869,9 +1867,8 @@ impl InferenceContext<'_> {
                         )
                     },
                     |this, lt_ref| this.make_lifetime(lt_ref),
-                ) {
-                    substs.push(g);
-                }
+                );
+                substs.push(arg);
             }
         };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index ae92b8b8966..00b1f53857b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -375,7 +375,7 @@ impl<'a> TyLoweringContext<'a> {
                         counter.set(idx + count_impl_traits(type_ref) as u16);
                         let (
                             _parent_params,
-                            self_params,
+                            self_param,
                             type_params,
                             const_params,
                             _impl_trait_params,
@@ -386,7 +386,7 @@ impl<'a> TyLoweringContext<'a> {
                             .provenance_split();
                         TyKind::BoundVar(BoundVar::new(
                             self.in_binders,
-                            idx as usize + self_params + type_params + const_params,
+                            idx as usize + self_param as usize + type_params + const_params,
                         ))
                         .intern(Interner)
                     }
@@ -817,14 +817,14 @@ impl<'a> TyLoweringContext<'a> {
         let def_generics = generics(self.db.upcast(), def);
         let (
             parent_params,
-            self_params,
+            self_param,
             type_params,
             const_params,
             impl_trait_params,
             lifetime_params,
         ) = def_generics.provenance_split();
         let item_len =
-            self_params + type_params + const_params + impl_trait_params + lifetime_params;
+            self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
         let total_len = parent_params + item_len;
 
         let ty_error = TyKind::Error.intern(Interner).cast(Interner);
@@ -832,18 +832,16 @@ impl<'a> TyLoweringContext<'a> {
         let mut def_generic_iter = def_generics.iter_id();
 
         let fill_self_params = || {
-            for x in explicit_self_ty
-                .into_iter()
-                .map(|x| x.cast(Interner))
-                .chain(iter::repeat(ty_error.clone()))
-                .take(self_params)
-            {
+            if self_param {
+                let self_ty =
+                    explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(|| ty_error.clone());
+
                 if let Some(id) = def_generic_iter.next() {
                     assert!(matches!(
                         id,
                         GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
                     ));
-                    substs.push(x);
+                    substs.push(self_ty);
                 }
             }
         };
@@ -854,11 +852,11 @@ impl<'a> TyLoweringContext<'a> {
                 fill_self_params();
             }
             let expected_num = if generic_args.has_self_type {
-                self_params + type_params + const_params
+                self_param as usize + type_params + const_params
             } else {
                 type_params + const_params
             };
-            let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
+            let skip = if generic_args.has_self_type && !self_param { 1 } else { 0 };
             // if args are provided, it should be all of them, but we can't rely on that
             for arg in generic_args
                 .args
@@ -868,7 +866,7 @@ impl<'a> TyLoweringContext<'a> {
                 .take(expected_num)
             {
                 if let Some(id) = def_generic_iter.next() {
-                    if let Some(x) = generic_arg_to_chalk(
+                    let arg = generic_arg_to_chalk(
                         self.db,
                         id,
                         arg,
@@ -876,13 +874,9 @@ impl<'a> TyLoweringContext<'a> {
                         |_, type_ref| self.lower_ty(type_ref),
                         |_, const_ref, ty| self.lower_const(const_ref, ty),
                         |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
-                    ) {
-                        had_explicit_args = true;
-                        substs.push(x);
-                    } else {
-                        // we just filtered them out
-                        never!("Unexpected lifetime argument");
-                    }
+                    );
+                    had_explicit_args = true;
+                    substs.push(arg);
                 }
             }
 
@@ -895,7 +889,7 @@ impl<'a> TyLoweringContext<'a> {
                 // Taking into the fact that def_generic_iter will always have lifetimes at the end
                 // Should have some test cases tho to test this behaviour more properly
                 if let Some(id) = def_generic_iter.next() {
-                    if let Some(x) = generic_arg_to_chalk(
+                    let arg = generic_arg_to_chalk(
                         self.db,
                         id,
                         arg,
@@ -903,13 +897,9 @@ impl<'a> TyLoweringContext<'a> {
                         |_, type_ref| self.lower_ty(type_ref),
                         |_, const_ref, ty| self.lower_const(const_ref, ty),
                         |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
-                    ) {
-                        had_explicit_args = true;
-                        substs.push(x);
-                    } else {
-                        // Never return a None explicitly
-                        never!("Unexpected None by generic_arg_to_chalk");
-                    }
+                    );
+                    had_explicit_args = true;
+                    substs.push(arg);
                 }
             }
         } else {
@@ -2170,7 +2160,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
 /// Checks if the provided generic arg matches its expected kind, then lower them via
 /// provided closures. Use unknown if there was kind mismatch.
 ///
-/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
 pub(crate) fn generic_arg_to_chalk<'a, T>(
     db: &dyn HirDatabase,
     kind_id: GenericParamId,
@@ -2179,7 +2168,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
     for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
     for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
     for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
-) -> Option<crate::GenericArg> {
+) -> crate::GenericArg {
     let kind = match kind_id {
         GenericParamId::TypeParamId(_) => ParamKind::Type,
         GenericParamId::ConstParamId(id) => {
@@ -2188,7 +2177,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
         }
         GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
     };
-    Some(match (arg, kind) {
+    match (arg, kind) {
         (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
         (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
         (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
@@ -2201,11 +2190,12 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
             // as types. Maybe here is not the best place to do it, but
             // it works.
             if let TypeRef::Path(p) = t {
-                let p = p.mod_path()?;
-                if p.kind == PathKind::Plain {
-                    if let [n] = p.segments() {
-                        let c = ConstRef::Path(n.clone());
-                        return Some(for_const(this, &c, c_ty).cast(Interner));
+                if let Some(p) = p.mod_path() {
+                    if p.kind == PathKind::Plain {
+                        if let [n] = p.segments() {
+                            let c = ConstRef::Path(n.clone());
+                            return for_const(this, &c, c_ty).cast(Interner);
+                        }
                     }
                 }
             }
@@ -2214,7 +2204,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
         (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
         (GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
         (GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
-    })
+    }
 }
 
 pub(crate) fn const_or_path_to_chalk(