mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Change Ty::Param to contain param ID
This commit is contained in:
parent
f8b7b64bce
commit
ed25cf70d5
11 changed files with 136 additions and 127 deletions
|
@ -3,10 +3,10 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId,
|
db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, TypeParamId,
|
||||||
};
|
};
|
||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
use ra_db::{salsa, CrateId};
|
use ra_db::{impl_intern_key, salsa, CrateId};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -37,10 +37,10 @@ pub trait HirDatabase: DefDatabase {
|
||||||
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
|
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::impl_trait_query)]
|
#[salsa::invoke(crate::lower::impl_trait_query)]
|
||||||
fn impl_trait(&self, def: ImplId) -> Option<TraitRef>;
|
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::field_types_query)]
|
#[salsa::invoke(crate::lower::field_types_query)]
|
||||||
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
|
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::callable_item_sig)]
|
#[salsa::invoke(crate::callable_item_sig)]
|
||||||
fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig;
|
fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig;
|
||||||
|
@ -49,8 +49,7 @@ pub trait HirDatabase: DefDatabase {
|
||||||
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
|
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
|
||||||
fn generic_predicates_for_param(
|
fn generic_predicates_for_param(
|
||||||
&self,
|
&self,
|
||||||
def: GenericDefId,
|
param_id: TypeParamId,
|
||||||
param_idx: u32,
|
|
||||||
) -> Arc<[GenericPredicate]>;
|
) -> Arc<[GenericPredicate]>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
||||||
|
@ -77,6 +76,8 @@ pub trait HirDatabase: DefDatabase {
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
|
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
|
fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
|
||||||
|
#[salsa::interned]
|
||||||
fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
|
fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
|
fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
|
||||||
|
@ -117,3 +118,7 @@ fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
|
||||||
fn hir_database_is_object_safe() {
|
fn hir_database_is_object_safe() {
|
||||||
fn _assert_object_safe(_: &dyn HirDatabase) {}
|
fn _assert_object_safe(_: &dyn HirDatabase) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub struct GlobalTypeParamId(salsa::InternId);
|
||||||
|
impl_intern_key!(GlobalTypeParamId);
|
||||||
|
|
|
@ -57,8 +57,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let trait_ref = db.impl_trait(impl_id)?;
|
let trait_ref = db.impl_trait(impl_id)?;
|
||||||
|
|
||||||
// `CoerseUnsized` has one generic parameter for the target type.
|
// `CoerseUnsized` has one generic parameter for the target type.
|
||||||
let cur_from_ty = trait_ref.substs.0.get(0)?;
|
let cur_from_ty = trait_ref.value.substs.0.get(0)?;
|
||||||
let cur_to_ty = trait_ref.substs.0.get(1)?;
|
let cur_to_ty = trait_ref.value.substs.0.get(1)?;
|
||||||
|
|
||||||
match (&cur_from_ty, cur_to_ty) {
|
match (&cur_from_ty, cur_to_ty) {
|
||||||
(ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => {
|
(ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => {
|
||||||
|
@ -66,8 +66,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
// This works for smart-pointer-like coercion, which covers all impls from std.
|
// This works for smart-pointer-like coercion, which covers all impls from std.
|
||||||
st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| {
|
st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| {
|
||||||
match (ty1, ty2) {
|
match (ty1, ty2) {
|
||||||
(Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. })
|
(Ty::Bound(idx1), Ty::Bound(idx2))
|
||||||
if p1 != p2 =>
|
if idx1 != idx2 =>
|
||||||
{
|
{
|
||||||
Some(((*ctor1, *ctor2), i))
|
Some(((*ctor1, *ctor2), i))
|
||||||
}
|
}
|
||||||
|
@ -256,8 +256,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let unsize_generic_index = {
|
let unsize_generic_index = {
|
||||||
let mut index = None;
|
let mut index = None;
|
||||||
let mut multiple_param = false;
|
let mut multiple_param = false;
|
||||||
field_tys[last_field_id].walk(&mut |ty| match ty {
|
field_tys[last_field_id].value.walk(&mut |ty| match ty {
|
||||||
&Ty::Param { idx, .. } => {
|
&Ty::Bound(idx) => {
|
||||||
if index.is_none() {
|
if index.is_none() {
|
||||||
index = Some(idx);
|
index = Some(idx);
|
||||||
} else if Some(idx) != index {
|
} else if Some(idx) != index {
|
||||||
|
@ -276,8 +276,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
// Check other fields do not involve it.
|
// Check other fields do not involve it.
|
||||||
let mut multiple_used = false;
|
let mut multiple_used = false;
|
||||||
fields.for_each(|(field_id, _data)| {
|
fields.for_each(|(field_id, _data)| {
|
||||||
field_tys[field_id].walk(&mut |ty| match ty {
|
field_tys[field_id].value.walk(&mut |ty| match ty {
|
||||||
&Ty::Param { idx, .. } if idx == unsize_generic_index => {
|
&Ty::Bound(idx) if idx == unsize_generic_index => {
|
||||||
multiple_used = true
|
multiple_used = true
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -236,8 +236,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
self.result.record_field_resolutions.insert(field.expr, field_def);
|
self.result.record_field_resolutions.insert(field.expr, field_def);
|
||||||
}
|
}
|
||||||
let field_ty = field_def
|
let field_ty = field_def
|
||||||
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone())
|
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs));
|
||||||
.subst(&substs);
|
|
||||||
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
|
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
|
||||||
}
|
}
|
||||||
if let Some(expr) = spread {
|
if let Some(expr) = spread {
|
||||||
|
@ -686,7 +685,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
if let TypeCtor::FnDef(def) = a_ty.ctor {
|
if let TypeCtor::FnDef(def) = a_ty.ctor {
|
||||||
let generic_predicates = self.db.generic_predicates(def.into());
|
let generic_predicates = self.db.generic_predicates(def.into());
|
||||||
for predicate in generic_predicates.iter() {
|
for predicate in generic_predicates.iter() {
|
||||||
let predicate = predicate.clone().subst(&a_ty.parameters);
|
let predicate = predicate.clone().subst_type_params(self.db, def.into(), &a_ty.parameters);
|
||||||
if let Some(obligation) = Obligation::from_predicate(predicate) {
|
if let Some(obligation) = Obligation::from_predicate(predicate) {
|
||||||
self.obligations.push(obligation);
|
self.obligations.push(obligation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use hir_expand::name::Name;
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use super::{BindingMode, InferenceContext};
|
use super::{BindingMode, InferenceContext};
|
||||||
use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk};
|
use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor};
|
||||||
|
|
||||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
fn infer_tuple_struct_pat(
|
fn infer_tuple_struct_pat(
|
||||||
|
@ -34,8 +34,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let expected_ty = var_data
|
let expected_ty = var_data
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|d| d.field(&Name::new_tuple_field(i)))
|
.and_then(|d| d.field(&Name::new_tuple_field(i)))
|
||||||
.map_or(Ty::Unknown, |field| field_tys[field].clone())
|
.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
|
||||||
.subst(&substs);
|
|
||||||
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
||||||
self.infer_pat(subpat, &expected_ty, default_bm);
|
self.infer_pat(subpat, &expected_ty, default_bm);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +64,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
for subpat in subpats {
|
for subpat in subpats {
|
||||||
let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
|
let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
|
||||||
let expected_ty =
|
let expected_ty =
|
||||||
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs);
|
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
|
||||||
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
||||||
self.infer_pat(subpat.pat, &expected_ty, default_bm);
|
self.infer_pat(subpat.pat, &expected_ty, default_bm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,10 @@ use std::{fmt, iter, mem};
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
|
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
|
||||||
HasModule, Lookup, TraitId, TypeAliasId,
|
HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
|
||||||
use ra_db::{impl_intern_key, salsa, CrateId};
|
use ra_db::{impl_intern_key, salsa, CrateId};
|
||||||
|
use hir_expand::name::Name;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
|
@ -288,14 +288,7 @@ pub enum Ty {
|
||||||
Projection(ProjectionTy),
|
Projection(ProjectionTy),
|
||||||
|
|
||||||
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
||||||
Param {
|
Param(TypeParamId),
|
||||||
/// The index of the parameter (starting with parameters from the
|
|
||||||
/// surrounding impl, then the current function).
|
|
||||||
idx: u32,
|
|
||||||
/// The name of the parameter, for displaying.
|
|
||||||
// FIXME get rid of this
|
|
||||||
name: Name,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A bound type variable. Used during trait resolution to represent Chalk
|
/// A bound type variable. Used during trait resolution to represent Chalk
|
||||||
/// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
|
/// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
|
||||||
|
@ -366,15 +359,15 @@ impl Substs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
|
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
|
||||||
pub(crate) fn identity(generic_params: &Generics) -> Substs {
|
pub(crate) fn type_params(generic_params: &Generics) -> Substs {
|
||||||
Substs(
|
Substs(
|
||||||
generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone().unwrap_or_else(Name::missing) }).collect(),
|
generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return Substs that replace each parameter by a bound variable.
|
/// Return Substs that replace each parameter by a bound variable.
|
||||||
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
|
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
|
||||||
Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect())
|
Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
|
pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
|
||||||
|
@ -422,11 +415,6 @@ impl SubstsBuilder {
|
||||||
self.fill((starting_from..).map(Ty::Bound))
|
self.fill((starting_from..).map(Ty::Bound))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_with_params(self) -> Self {
|
|
||||||
let start = self.vec.len() as u32;
|
|
||||||
self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fill_with_unknown(self) -> Self {
|
pub fn fill_with_unknown(self) -> Self {
|
||||||
self.fill(iter::repeat(Ty::Unknown))
|
self.fill(iter::repeat(Ty::Unknown))
|
||||||
}
|
}
|
||||||
|
@ -762,13 +750,19 @@ pub trait TypeWalk {
|
||||||
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
||||||
/// if `self` is `&[T]`, where type parameter T has index 0, and the
|
/// if `self` is `&[T]`, where type parameter T has index 0, and the
|
||||||
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
|
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
|
||||||
fn subst(self, substs: &Substs) -> Self
|
// TODO: this should mostly not be used anymore
|
||||||
|
fn subst_type_params(self, db: &impl HirDatabase, def: GenericDefId, substs: &Substs) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
let generics = generics(db, def);
|
||||||
self.fold(&mut |ty| match ty {
|
self.fold(&mut |ty| match ty {
|
||||||
Ty::Param { idx, name } => {
|
Ty::Param(id) => {
|
||||||
substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
|
if let Some(idx) = generics.param_idx(id) {
|
||||||
|
substs.get(idx as usize).cloned().unwrap_or(Ty::Param(id))
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty => ty,
|
ty => ty,
|
||||||
})
|
})
|
||||||
|
@ -1042,7 +1036,18 @@ impl HirDisplay for Ty {
|
||||||
match self {
|
match self {
|
||||||
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
|
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
|
||||||
Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
|
Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
|
||||||
Ty::Param { name, .. } => write!(f, "{}", name)?,
|
Ty::Param(id) => {
|
||||||
|
let generic_params = f.db.generic_params(id.parent);
|
||||||
|
let param_data = &generic_params.types[id.local_id];
|
||||||
|
match param_data.provenance {
|
||||||
|
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||||
|
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
||||||
|
}
|
||||||
|
TypeParamProvenance::ArgumentImplTrait => {
|
||||||
|
write!(f, "impl TODO")?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Ty::Bound(idx) => write!(f, "?{}", idx)?,
|
Ty::Bound(idx) => write!(f, "?{}", idx)?,
|
||||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -30,7 +30,7 @@ use crate::{
|
||||||
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
|
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
|
||||||
TraitEnvironment, TraitRef, Ty, TypeCtor,
|
TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_def::TypeParamId;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TyLoweringContext<'a, DB: HirDatabase> {
|
pub struct TyLoweringContext<'a, DB: HirDatabase> {
|
||||||
|
@ -145,7 +145,16 @@ impl Ty {
|
||||||
ImplTraitLoweringMode::Param => {
|
ImplTraitLoweringMode::Param => {
|
||||||
let idx = ctx.impl_trait_counter.get();
|
let idx = ctx.impl_trait_counter.get();
|
||||||
ctx.impl_trait_counter.set(idx + 1);
|
ctx.impl_trait_counter.set(idx + 1);
|
||||||
Ty::Param { idx: idx as u32, name: Name::missing() }
|
if let Some(def) = ctx.resolver.generic_def() {
|
||||||
|
let generics = generics(ctx.db, def);
|
||||||
|
let param = generics
|
||||||
|
.iter()
|
||||||
|
.nth(idx as usize)
|
||||||
|
.map_or(Ty::Unknown, |(id, _)| Ty::Param(id));
|
||||||
|
param
|
||||||
|
} else {
|
||||||
|
Ty::Unknown
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImplTraitLoweringMode::Variable => {
|
ImplTraitLoweringMode::Variable => {
|
||||||
let idx = ctx.impl_trait_counter.get();
|
let idx = ctx.impl_trait_counter.get();
|
||||||
|
@ -176,7 +185,7 @@ impl Ty {
|
||||||
fn from_hir_only_param(
|
fn from_hir_only_param(
|
||||||
ctx: &TyLoweringContext<'_, impl HirDatabase>,
|
ctx: &TyLoweringContext<'_, impl HirDatabase>,
|
||||||
type_ref: &TypeRef,
|
type_ref: &TypeRef,
|
||||||
) -> Option<u32> {
|
) -> Option<TypeParamId> {
|
||||||
let path = match type_ref {
|
let path = match type_ref {
|
||||||
TypeRef::Path(path) => path,
|
TypeRef::Path(path) => path,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
@ -192,9 +201,7 @@ impl Ty {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
if let TypeNs::GenericParam(param_id) = resolution {
|
if let TypeNs::GenericParam(param_id) = resolution {
|
||||||
let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
|
Some(param_id)
|
||||||
let idx = generics.param_idx(param_id);
|
|
||||||
Some(idx)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -256,20 +263,18 @@ impl Ty {
|
||||||
TypeNs::GenericParam(param_id) => {
|
TypeNs::GenericParam(param_id) => {
|
||||||
let generics =
|
let generics =
|
||||||
generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
|
generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
|
||||||
let idx = generics.param_idx(param_id);
|
|
||||||
match ctx.type_param_mode {
|
match ctx.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => {
|
TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
|
||||||
// FIXME: maybe return name in resolution?
|
TypeParamLoweringMode::Variable => {
|
||||||
let name = generics.param_name(param_id);
|
let idx = generics.param_idx(param_id).expect("matching generics");
|
||||||
Ty::Param { idx, name }
|
Ty::Bound(idx)
|
||||||
}
|
}
|
||||||
TypeParamLoweringMode::Variable => Ty::Bound(idx),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeNs::SelfType(impl_id) => {
|
TypeNs::SelfType(impl_id) => {
|
||||||
let generics = generics(ctx.db, impl_id.into());
|
let generics = generics(ctx.db, impl_id.into());
|
||||||
let substs = match ctx.type_param_mode {
|
let substs = match ctx.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => Substs::identity(&generics),
|
TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
|
||||||
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
|
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
|
||||||
};
|
};
|
||||||
ctx.db.impl_self_ty(impl_id).subst(&substs)
|
ctx.db.impl_self_ty(impl_id).subst(&substs)
|
||||||
|
@ -277,7 +282,7 @@ impl Ty {
|
||||||
TypeNs::AdtSelfType(adt) => {
|
TypeNs::AdtSelfType(adt) => {
|
||||||
let generics = generics(ctx.db, adt.into());
|
let generics = generics(ctx.db, adt.into());
|
||||||
let substs = match ctx.type_param_mode {
|
let substs = match ctx.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => Substs::identity(&generics),
|
TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
|
||||||
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
|
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
|
||||||
};
|
};
|
||||||
ctx.db.ty(adt.into()).subst(&substs)
|
ctx.db.ty(adt.into()).subst(&substs)
|
||||||
|
@ -319,20 +324,28 @@ impl Ty {
|
||||||
self_ty: Ty,
|
self_ty: Ty,
|
||||||
segment: PathSegment<'_>,
|
segment: PathSegment<'_>,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
let param_idx = match self_ty {
|
|
||||||
Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx,
|
|
||||||
Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx,
|
|
||||||
_ => return Ty::Unknown, // Error: Ambiguous associated type
|
|
||||||
};
|
|
||||||
let def = match ctx.resolver.generic_def() {
|
let def = match ctx.resolver.generic_def() {
|
||||||
Some(def) => def,
|
Some(def) => def,
|
||||||
None => return Ty::Unknown, // this can't actually happen
|
None => return Ty::Unknown, // this can't actually happen
|
||||||
};
|
};
|
||||||
let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx);
|
let param_id = match self_ty {
|
||||||
|
Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id,
|
||||||
|
Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => {
|
||||||
|
let generics = generics(ctx.db, def);
|
||||||
|
let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
return Ty::Unknown;
|
||||||
|
};
|
||||||
|
param_id
|
||||||
|
},
|
||||||
|
_ => return Ty::Unknown, // Error: Ambiguous associated type
|
||||||
|
};
|
||||||
|
let predicates = ctx.db.generic_predicates_for_param(param_id);
|
||||||
let traits_from_env = predicates.iter().filter_map(|pred| match pred {
|
let traits_from_env = predicates.iter().filter_map(|pred| match pred {
|
||||||
GenericPredicate::Implemented(tr) => {
|
GenericPredicate::Implemented(tr) => {
|
||||||
if let Ty::Param { idx, .. } = tr.self_ty() {
|
if let Ty::Param(id) = tr.self_ty() {
|
||||||
if *idx == param_idx {
|
if *id == param_id {
|
||||||
return Some(tr.trait_);
|
return Some(tr.trait_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,13 +543,12 @@ impl GenericPredicate {
|
||||||
let generic_def = ctx.resolver.generic_def().expect("generics in scope");
|
let generic_def = ctx.resolver.generic_def().expect("generics in scope");
|
||||||
let generics = generics(ctx.db, generic_def);
|
let generics = generics(ctx.db, generic_def);
|
||||||
let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
|
let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
|
||||||
let idx = generics.param_idx(param_id);
|
|
||||||
match ctx.type_param_mode {
|
match ctx.type_param_mode {
|
||||||
TypeParamLoweringMode::Placeholder => {
|
TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
|
||||||
let name = generics.param_name(param_id);
|
TypeParamLoweringMode::Variable => {
|
||||||
Ty::Param { idx, name }
|
let idx = generics.param_idx(param_id).expect("matching generics");
|
||||||
|
Ty::Bound(idx)
|
||||||
}
|
}
|
||||||
TypeParamLoweringMode::Variable => Ty::Bound(idx),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -599,17 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig {
|
||||||
pub(crate) fn field_types_query(
|
pub(crate) fn field_types_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
variant_id: VariantId,
|
variant_id: VariantId,
|
||||||
) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
|
) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> {
|
||||||
let var_data = variant_data(db, variant_id);
|
let var_data = variant_data(db, variant_id);
|
||||||
let resolver = match variant_id {
|
let (resolver, def): (_, GenericDefId) = match variant_id {
|
||||||
VariantId::StructId(it) => it.resolver(db),
|
VariantId::StructId(it) => (it.resolver(db), it.into()),
|
||||||
VariantId::UnionId(it) => it.resolver(db),
|
VariantId::UnionId(it) => (it.resolver(db), it.into()),
|
||||||
VariantId::EnumVariantId(it) => it.parent.resolver(db),
|
VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()),
|
||||||
};
|
};
|
||||||
|
let generics = generics(db, def);
|
||||||
let mut res = ArenaMap::default();
|
let mut res = ArenaMap::default();
|
||||||
let ctx = TyLoweringContext::new(db, &resolver);
|
let ctx = TyLoweringContext::new(db, &resolver)
|
||||||
|
.with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
for (field_id, field_data) in var_data.fields().iter() {
|
for (field_id, field_data) in var_data.fields().iter() {
|
||||||
res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref))
|
res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref)))
|
||||||
}
|
}
|
||||||
Arc::new(res)
|
Arc::new(res)
|
||||||
}
|
}
|
||||||
|
@ -624,23 +638,20 @@ pub(crate) fn field_types_query(
|
||||||
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
|
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
|
||||||
pub(crate) fn generic_predicates_for_param_query(
|
pub(crate) fn generic_predicates_for_param_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
def: GenericDefId,
|
param_id: TypeParamId,
|
||||||
param_idx: u32,
|
|
||||||
) -> Arc<[GenericPredicate]> {
|
) -> Arc<[GenericPredicate]> {
|
||||||
let resolver = def.resolver(db);
|
let resolver = param_id.parent.resolver(db);
|
||||||
let ctx = TyLoweringContext::new(db, &resolver);
|
let ctx = TyLoweringContext::new(db, &resolver);
|
||||||
let generics = generics(db, def);
|
// let generics = generics(db, def);
|
||||||
resolver
|
resolver
|
||||||
.where_predicates_in_scope()
|
.where_predicates_in_scope()
|
||||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
// we have to filter out all other predicates *first*, before attempting to lower them
|
||||||
.filter(|pred| match &pred.target {
|
.filter(|pred| match &pred.target {
|
||||||
WherePredicateTarget::TypeRef(type_ref) => {
|
WherePredicateTarget::TypeRef(type_ref) => {
|
||||||
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx)
|
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
|
||||||
}
|
}
|
||||||
WherePredicateTarget::TypeParam(local_id) => {
|
WherePredicateTarget::TypeParam(local_id) => {
|
||||||
let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id };
|
*local_id == param_id.local_id
|
||||||
let idx = generics.param_idx(param_id);
|
|
||||||
idx == param_idx
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
|
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
|
||||||
|
@ -650,8 +661,7 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
pub(crate) fn generic_predicates_for_param_recover(
|
pub(crate) fn generic_predicates_for_param_recover(
|
||||||
_db: &impl HirDatabase,
|
_db: &impl HirDatabase,
|
||||||
_cycle: &[String],
|
_cycle: &[String],
|
||||||
_def: &GenericDefId,
|
_param_id: &TypeParamId,
|
||||||
_param_idx: &u32,
|
|
||||||
) -> Arc<[GenericPredicate]> {
|
) -> Arc<[GenericPredicate]> {
|
||||||
Arc::new([])
|
Arc::new([])
|
||||||
}
|
}
|
||||||
|
@ -905,12 +915,12 @@ pub(crate) fn impl_self_ty_recover(
|
||||||
Binders::new(generics.len(), Ty::Unknown)
|
Binders::new(generics.len(), Ty::Unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> {
|
pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
|
||||||
let impl_data = db.impl_data(impl_id);
|
let impl_data = db.impl_data(impl_id);
|
||||||
let resolver = impl_id.resolver(db);
|
let resolver = impl_id.resolver(db);
|
||||||
let generics = generics(db, impl_id.into());
|
let ctx = TyLoweringContext::new(db, &resolver)
|
||||||
let ctx = TyLoweringContext::new(db, &resolver);
|
.with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics));
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
let target_trait = impl_data.target_trait.as_ref()?;
|
let target_trait = impl_data.target_trait.as_ref()?;
|
||||||
TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone()))
|
Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?))
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ impl CrateImplBlocks {
|
||||||
for impl_id in module_data.scope.impls() {
|
for impl_id in module_data.scope.impls() {
|
||||||
match db.impl_trait(impl_id) {
|
match db.impl_trait(impl_id) {
|
||||||
Some(tr) => {
|
Some(tr) => {
|
||||||
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
|
res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
|
|
|
@ -697,7 +697,7 @@ fn test<U, T: Trait<U>>(t: T) {
|
||||||
[71; 72) 't': T
|
[71; 72) 't': T
|
||||||
[77; 96) '{ ...d(); }': ()
|
[77; 96) '{ ...d(); }': ()
|
||||||
[83; 84) 't': T
|
[83; 84) 't': T
|
||||||
[83; 93) 't.method()': [missing name]
|
[83; 93) 't.method()': U
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -822,8 +822,7 @@ fn test<T: ApplyL>() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
|
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
|
||||||
// FIXME: fix type parameter names going missing when going through Chalk
|
assert_eq!(t, "ApplyL::Out<T>");
|
||||||
assert_eq!(t, "ApplyL::Out<[missing name]>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -142,8 +142,9 @@ impl ToChalk for Ty {
|
||||||
let substitution = proj_ty.parameters.to_chalk(db);
|
let substitution = proj_ty.parameters.to_chalk(db);
|
||||||
chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern()
|
chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern()
|
||||||
}
|
}
|
||||||
Ty::Param { idx, .. } => {
|
Ty::Param(id) => {
|
||||||
PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }
|
let interned_id = db.intern_type_param_id(id);
|
||||||
|
PlaceholderIndex { ui: UniverseIndex::ROOT, idx: interned_id.as_intern_id().as_usize() }
|
||||||
.to_ty::<TypeFamily>()
|
.to_ty::<TypeFamily>()
|
||||||
}
|
}
|
||||||
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
|
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
|
||||||
|
@ -177,7 +178,8 @@ impl ToChalk for Ty {
|
||||||
},
|
},
|
||||||
chalk_ir::TyData::Placeholder(idx) => {
|
chalk_ir::TyData::Placeholder(idx) => {
|
||||||
assert_eq!(idx.ui, UniverseIndex::ROOT);
|
assert_eq!(idx.ui, UniverseIndex::ROOT);
|
||||||
Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
|
let interned_id = crate::db::GlobalTypeParamId::from_intern_id(crate::salsa::InternId::from(idx.idx));
|
||||||
|
Ty::Param(db.lookup_intern_type_param_id(interned_id))
|
||||||
}
|
}
|
||||||
chalk_ir::TyData::Alias(proj) => {
|
chalk_ir::TyData::Alias(proj) => {
|
||||||
let associated_ty = from_chalk(db, proj.associated_ty_id);
|
let associated_ty = from_chalk(db, proj.associated_ty_id);
|
||||||
|
@ -524,7 +526,7 @@ fn convert_where_clauses(
|
||||||
// skip errored predicates completely
|
// skip errored predicates completely
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.push(pred.clone().subst(substs).to_chalk(db));
|
result.push(pred.clone().subst_type_params(db, def, substs).to_chalk(db));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -709,12 +711,12 @@ fn impl_block_datum(
|
||||||
let trait_ref = db
|
let trait_ref = db
|
||||||
.impl_trait(impl_id)
|
.impl_trait(impl_id)
|
||||||
// ImplIds for impls where the trait ref can't be resolved should never reach Chalk
|
// ImplIds for impls where the trait ref can't be resolved should never reach Chalk
|
||||||
.expect("invalid impl passed to Chalk");
|
.expect("invalid impl passed to Chalk")
|
||||||
|
.value;
|
||||||
let impl_data = db.impl_data(impl_id);
|
let impl_data = db.impl_data(impl_id);
|
||||||
|
|
||||||
let generic_params = generics(db, impl_id.into());
|
let generic_params = generics(db, impl_id.into());
|
||||||
let bound_vars = Substs::bound_vars(&generic_params);
|
let bound_vars = Substs::bound_vars(&generic_params);
|
||||||
let trait_ref = trait_ref.subst(&bound_vars);
|
|
||||||
let trait_ = trait_ref.trait_;
|
let trait_ = trait_ref.trait_;
|
||||||
let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
|
let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
|
||||||
chalk_rust_ir::ImplType::Local
|
chalk_rust_ir::ImplType::Local
|
||||||
|
@ -789,20 +791,18 @@ fn type_alias_associated_ty_value(
|
||||||
_ => panic!("assoc ty value should be in impl"),
|
_ => panic!("assoc ty value should be in impl"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved
|
let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
|
||||||
|
|
||||||
let assoc_ty = db
|
let assoc_ty = db
|
||||||
.trait_data(trait_ref.trait_)
|
.trait_data(trait_ref.trait_)
|
||||||
.associated_type_by_name(&type_alias_data.name)
|
.associated_type_by_name(&type_alias_data.name)
|
||||||
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
||||||
let generic_params = generics(db, impl_id.into());
|
let ty = db.ty(type_alias.into());
|
||||||
let bound_vars = Substs::bound_vars(&generic_params);
|
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
|
||||||
let ty = db.ty(type_alias.into()).subst(&bound_vars);
|
|
||||||
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
|
|
||||||
let value = chalk_rust_ir::AssociatedTyValue {
|
let value = chalk_rust_ir::AssociatedTyValue {
|
||||||
impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
|
impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
|
||||||
associated_ty_id: assoc_ty.to_chalk(db),
|
associated_ty_id: assoc_ty.to_chalk(db),
|
||||||
value: make_binders(value_bound, bound_vars.len()),
|
value: make_binders(value_bound, ty.num_binders),
|
||||||
};
|
};
|
||||||
Arc::new(value)
|
Arc::new(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,23 +99,19 @@ pub(crate) struct Generics {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Generics {
|
impl Generics {
|
||||||
pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
|
pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
|
||||||
self.parent_generics
|
self.parent_generics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|it| it.params.types.iter())
|
.flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
|
||||||
.chain(self.params.types.iter())
|
.chain(self.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)))
|
||||||
.enumerate()
|
|
||||||
.map(|(i, (_local_id, p))| (i as u32, p))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
|
pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
|
||||||
self.parent_generics
|
self.parent_generics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|it| it.params.types.iter())
|
.flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
|
||||||
.enumerate()
|
|
||||||
.map(|(i, (_local_id, p))| (i as u32, p))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn len(&self) -> usize {
|
pub(crate) fn len(&self) -> usize {
|
||||||
|
@ -137,16 +133,11 @@ impl Generics {
|
||||||
(self_params, list_params, impl_trait_params)
|
(self_params, list_params, impl_trait_params)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 {
|
pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
|
||||||
self.find_param(param).0
|
Some(self.find_param(param)?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn param_name(&self, param: TypeParamId) -> Name {
|
fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
|
||||||
// FIXME make this return Option
|
|
||||||
self.find_param(param).1.name.clone().unwrap_or_else(Name::missing)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) {
|
|
||||||
if param.parent == self.def {
|
if param.parent == self.def {
|
||||||
let (idx, (_local_id, data)) = self
|
let (idx, (_local_id, data)) = self
|
||||||
.params
|
.params
|
||||||
|
@ -156,9 +147,10 @@ impl Generics {
|
||||||
.find(|(_, (idx, _))| *idx == param.local_id)
|
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (_total, parent_len, _child) = self.len_split();
|
let (_total, parent_len, _child) = self.len_split();
|
||||||
return ((parent_len + idx) as u32, data);
|
Some(((parent_len + idx) as u32, data))
|
||||||
|
} else {
|
||||||
|
self.parent_generics.as_ref().and_then(|g| g.find_param(param))
|
||||||
}
|
}
|
||||||
self.parent_generics.as_ref().unwrap().find_param(param)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue