mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-13 15:33:53 +00:00
There can only be one self param
This commit is contained in:
parent
c133c649a0
commit
3a66230a44
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user