mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 11:13:43 +00:00
Merge #2492
2492: Refactor generic parameteres lowering r=flodiebold a=matklad indices and parent params seem to be concerns, specific to `hir_ty`, so move them there. Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
7aac5f2b42
@ -15,7 +15,7 @@ use hir_def::{
|
||||
per_ns::PerNs,
|
||||
resolver::HasResolver,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
|
||||
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericParamId,
|
||||
HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
|
||||
Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
|
||||
};
|
||||
@ -857,8 +857,7 @@ impl Local {
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct GenericParam {
|
||||
pub(crate) parent: GenericDefId,
|
||||
pub(crate) idx: u32,
|
||||
pub(crate) id: GenericParamId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -262,10 +262,7 @@ impl SourceAnalyzer {
|
||||
) -> Option<PathResolution> {
|
||||
let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty {
|
||||
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
|
||||
TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam {
|
||||
parent: self.resolver.generic_def().unwrap(),
|
||||
idx,
|
||||
}),
|
||||
TypeNs::GenericParam(id) => PathResolution::GenericParam(GenericParam { id }),
|
||||
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
|
||||
PathResolution::Def(Adt::from(it).into())
|
||||
}
|
||||
@ -337,10 +334,7 @@ impl SourceAnalyzer {
|
||||
resolver::ScopeDef::PerNs(it) => it.into(),
|
||||
resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
|
||||
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
|
||||
resolver::ScopeDef::GenericParam(idx) => {
|
||||
let parent = self.resolver.generic_def().unwrap();
|
||||
ScopeDef::GenericParam(GenericParam { parent, idx })
|
||||
}
|
||||
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(GenericParam { id }),
|
||||
resolver::ScopeDef::Local(pat_id) => {
|
||||
let parent = self.resolver.body_owner().unwrap().into();
|
||||
ScopeDef::Local(Local { parent, pat_id })
|
||||
|
@ -5,20 +5,19 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::name::{self, AsName, Name};
|
||||
use ra_arena::Arena;
|
||||
use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase,
|
||||
src::HasSource,
|
||||
type_ref::{TypeBound, TypeRef},
|
||||
AdtId, AstItemDef, ContainerId, GenericDefId, Lookup,
|
||||
AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup,
|
||||
};
|
||||
|
||||
/// Data about a generic parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct GenericParam {
|
||||
// FIXME: give generic params proper IDs
|
||||
pub idx: u32,
|
||||
pub struct GenericParamData {
|
||||
pub name: Name,
|
||||
pub default: Option<TypeRef>,
|
||||
}
|
||||
@ -26,8 +25,7 @@ pub struct GenericParam {
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct GenericParams {
|
||||
pub parent_params: Option<Arc<GenericParams>>,
|
||||
pub params: Vec<GenericParam>,
|
||||
pub params: Arena<LocalGenericParamId, GenericParamData>,
|
||||
pub where_predicates: Vec<WherePredicate>,
|
||||
}
|
||||
|
||||
@ -46,51 +44,40 @@ impl GenericParams {
|
||||
db: &impl DefDatabase,
|
||||
def: GenericDefId,
|
||||
) -> Arc<GenericParams> {
|
||||
let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
|
||||
Arc::new(GenericParams::new(db, def.into(), parent_generics))
|
||||
Arc::new(GenericParams::new(db, def.into()))
|
||||
}
|
||||
|
||||
fn new(
|
||||
db: &impl DefDatabase,
|
||||
def: GenericDefId,
|
||||
parent_params: Option<Arc<GenericParams>>,
|
||||
) -> GenericParams {
|
||||
let mut generics =
|
||||
GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
|
||||
let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
|
||||
fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams {
|
||||
let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() };
|
||||
// FIXME: add `: Sized` bound for everything except for `Self` in traits
|
||||
match def {
|
||||
GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
|
||||
GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start),
|
||||
GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start),
|
||||
GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
|
||||
GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value),
|
||||
GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value),
|
||||
GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value),
|
||||
GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value),
|
||||
GenericDefId::TraitId(it) => {
|
||||
// traits get the Self type as an implicit first type parameter
|
||||
generics.params.push(GenericParam {
|
||||
idx: start,
|
||||
name: name::SELF_TYPE,
|
||||
default: None,
|
||||
});
|
||||
generics.fill(&it.source(db).value, start + 1);
|
||||
generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None });
|
||||
generics.fill(&it.source(db).value);
|
||||
// add super traits as bounds on Self
|
||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
||||
let self_param = TypeRef::Path(name::SELF_TYPE.into());
|
||||
generics.fill_bounds(&it.source(db).value, self_param);
|
||||
}
|
||||
GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
|
||||
GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value),
|
||||
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
|
||||
// type-parameter, but rather is a type-alias for impl's target
|
||||
// type, so this is handled by the resolver.
|
||||
GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start),
|
||||
GenericDefId::ImplId(it) => generics.fill(&it.source(db).value),
|
||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {}
|
||||
}
|
||||
|
||||
generics
|
||||
}
|
||||
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
self.fill_params(params, start)
|
||||
self.fill_params(params)
|
||||
}
|
||||
if let Some(where_clause) = node.where_clause() {
|
||||
self.fill_where_predicates(where_clause);
|
||||
@ -105,13 +92,13 @@ impl GenericParams {
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_params(&mut self, params: ast::TypeParamList, start: u32) {
|
||||
for (idx, type_param) in params.type_params().enumerate() {
|
||||
fn fill_params(&mut self, params: ast::TypeParamList) {
|
||||
for type_param in params.type_params() {
|
||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||
// FIXME: Use `Path::from_src`
|
||||
let default = type_param.default_type().map(TypeRef::from_ast);
|
||||
let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
|
||||
self.params.push(param);
|
||||
let param = GenericParamData { name: name.clone(), default };
|
||||
self.params.alloc(param);
|
||||
|
||||
let type_ref = TypeRef::Path(name.into());
|
||||
self.fill_bounds(&type_param, type_ref);
|
||||
@ -140,45 +127,7 @@ impl GenericParams {
|
||||
self.where_predicates.push(WherePredicate { type_ref, bound });
|
||||
}
|
||||
|
||||
pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
|
||||
self.params.iter().find(|p| &p.name == name)
|
||||
}
|
||||
|
||||
pub fn count_parent_params(&self) -> usize {
|
||||
self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn count_params_including_parent(&self) -> usize {
|
||||
let parent_count = self.count_parent_params();
|
||||
parent_count + self.params.len()
|
||||
}
|
||||
|
||||
fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
|
||||
if let Some(parent) = &self.parent_params {
|
||||
parent.for_each_param(f);
|
||||
}
|
||||
self.params.iter().for_each(f);
|
||||
}
|
||||
|
||||
pub fn params_including_parent(&self) -> Vec<&GenericParam> {
|
||||
let mut vec = Vec::with_capacity(self.count_params_including_parent());
|
||||
self.for_each_param(&mut |p| vec.push(p));
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
|
||||
let container = match def {
|
||||
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
||||
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
||||
GenericDefId::ConstId(it) => it.lookup(db).container,
|
||||
GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
|
||||
GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
|
||||
};
|
||||
|
||||
match container {
|
||||
ContainerId::ImplId(it) => Some(it.into()),
|
||||
ContainerId::TraitId(it) => Some(it.into()),
|
||||
ContainerId::ModuleId(_) => None,
|
||||
pub fn find_by_name(&self, name: &Name) -> Option<LocalGenericParamId> {
|
||||
self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
|
||||
}
|
||||
}
|
||||
|
@ -317,6 +317,16 @@ macro_rules! impl_froms {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct GenericParamId {
|
||||
pub parent: GenericDefId,
|
||||
pub local_id: LocalGenericParamId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct LocalGenericParamId(RawId);
|
||||
impl_arena_id!(LocalGenericParamId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum ContainerId {
|
||||
ModuleId(ModuleId),
|
||||
|
@ -18,12 +18,13 @@ use crate::{
|
||||
path::{Path, PathKind},
|
||||
per_ns::PerNs,
|
||||
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
||||
GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId,
|
||||
StructId, TraitId, TypeAliasId,
|
||||
GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
|
||||
StaticId, StructId, TraitId, TypeAliasId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Resolver {
|
||||
// FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton?
|
||||
scopes: Vec<Scope>,
|
||||
}
|
||||
|
||||
@ -58,7 +59,7 @@ enum Scope {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum TypeNs {
|
||||
SelfType(ImplId),
|
||||
GenericParam(u32),
|
||||
GenericParam(GenericParamId),
|
||||
AdtId(AdtId),
|
||||
AdtSelfType(AdtId),
|
||||
// Yup, enum variants are added to the types ns, but any usage of variant as
|
||||
@ -152,10 +153,13 @@ impl Resolver {
|
||||
Scope::ExprScope(_) => continue,
|
||||
Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue,
|
||||
|
||||
Scope::GenericParams { params, .. } => {
|
||||
if let Some(param) = params.find_by_name(first_name) {
|
||||
Scope::GenericParams { params, def } => {
|
||||
if let Some(local_id) = params.find_by_name(first_name) {
|
||||
let idx = if path.segments.len() == 1 { None } else { Some(1) };
|
||||
return Some((TypeNs::GenericParam(param.idx), idx));
|
||||
return Some((
|
||||
TypeNs::GenericParam(GenericParamId { local_id, parent: *def }),
|
||||
idx,
|
||||
));
|
||||
}
|
||||
}
|
||||
Scope::ImplBlockScope(impl_) => {
|
||||
@ -246,9 +250,9 @@ impl Resolver {
|
||||
}
|
||||
Scope::ExprScope(_) => continue,
|
||||
|
||||
Scope::GenericParams { params, .. } if n_segments > 1 => {
|
||||
if let Some(param) = params.find_by_name(first_name) {
|
||||
let ty = TypeNs::GenericParam(param.idx);
|
||||
Scope::GenericParams { params, def } if n_segments > 1 => {
|
||||
if let Some(local_id) = params.find_by_name(first_name) {
|
||||
let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def });
|
||||
return Some(ResolveValueResult::Partial(ty, 1));
|
||||
}
|
||||
}
|
||||
@ -368,6 +372,7 @@ impl Resolver {
|
||||
) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a {
|
||||
self.scopes
|
||||
.iter()
|
||||
.rev()
|
||||
.filter_map(|scope| match scope {
|
||||
Scope::GenericParams { params, .. } => Some(params),
|
||||
_ => None,
|
||||
@ -376,14 +381,14 @@ impl Resolver {
|
||||
}
|
||||
|
||||
pub fn generic_def(&self) -> Option<GenericDefId> {
|
||||
self.scopes.iter().find_map(|scope| match scope {
|
||||
self.scopes.iter().rev().find_map(|scope| match scope {
|
||||
Scope::GenericParams { def, .. } => Some(*def),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn body_owner(&self) -> Option<DefWithBodyId> {
|
||||
self.scopes.iter().find_map(|scope| match scope {
|
||||
self.scopes.iter().rev().find_map(|scope| match scope {
|
||||
Scope::ExprScope(it) => Some(it.owner),
|
||||
_ => None,
|
||||
})
|
||||
@ -394,7 +399,7 @@ pub enum ScopeDef {
|
||||
PerNs(PerNs),
|
||||
ImplSelfType(ImplId),
|
||||
AdtSelfType(AdtId),
|
||||
GenericParam(u32),
|
||||
GenericParam(GenericParamId),
|
||||
Local(PatId),
|
||||
}
|
||||
|
||||
@ -425,9 +430,12 @@ impl Scope {
|
||||
});
|
||||
}
|
||||
}
|
||||
Scope::GenericParams { params, .. } => {
|
||||
for param in params.params.iter() {
|
||||
f(param.name.clone(), ScopeDef::GenericParam(param.idx))
|
||||
Scope::GenericParams { params, def } => {
|
||||
for (local_id, param) in params.params.iter() {
|
||||
f(
|
||||
param.name.clone(),
|
||||
ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }),
|
||||
)
|
||||
}
|
||||
}
|
||||
Scope::ImplBlockScope(i) => {
|
||||
|
@ -10,10 +10,10 @@ use hir_expand::name;
|
||||
use log::{info, warn};
|
||||
use ra_db::CrateId;
|
||||
|
||||
use crate::db::HirDatabase;
|
||||
|
||||
use super::{
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
traits::{InEnvironment, Solution},
|
||||
utils::generics,
|
||||
Canonical, Substs, Ty, TypeWalk,
|
||||
};
|
||||
|
||||
@ -54,8 +54,8 @@ fn deref_by_trait(
|
||||
};
|
||||
let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
|
||||
|
||||
let generic_params = db.generic_params(target.into());
|
||||
if generic_params.count_params_including_parent() != 1 {
|
||||
let generic_params = generics(db, target.into());
|
||||
if generic_params.len() != 1 {
|
||||
// the Target type + Deref trait should only have one generic parameter,
|
||||
// namely Deref's Self type
|
||||
return None;
|
||||
|
@ -6,7 +6,6 @@ use std::sync::Arc;
|
||||
use hir_def::{
|
||||
builtin_type::Signedness,
|
||||
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
||||
generics::GenericParams,
|
||||
path::{GenericArg, GenericArgs},
|
||||
resolver::resolver_for_expr,
|
||||
AdtId, ContainerId, Lookup, StructFieldId,
|
||||
@ -15,7 +14,11 @@ use hir_expand::name::{self, Name};
|
||||
use ra_syntax::ast::RangeOp;
|
||||
|
||||
use crate::{
|
||||
autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data,
|
||||
autoderef,
|
||||
db::HirDatabase,
|
||||
method_resolution, op,
|
||||
traits::InEnvironment,
|
||||
utils::{generics, variant_data, Generics},
|
||||
CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs,
|
||||
TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
|
||||
};
|
||||
@ -596,7 +599,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
Some((ty, func)) => {
|
||||
let ty = canonicalized_receiver.decanonicalize_ty(ty);
|
||||
self.write_method_resolution(tgt_expr, func);
|
||||
(ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into())))
|
||||
(ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
|
||||
}
|
||||
None => (receiver_ty, Ty::Unknown, None),
|
||||
};
|
||||
@ -653,16 +656,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
|
||||
fn substs_for_method_call(
|
||||
&mut self,
|
||||
def_generics: Option<Arc<GenericParams>>,
|
||||
def_generics: Option<Generics>,
|
||||
generic_args: Option<&GenericArgs>,
|
||||
receiver_ty: &Ty,
|
||||
) -> Substs {
|
||||
let (parent_param_count, param_count) =
|
||||
def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len()));
|
||||
let mut substs = Vec::with_capacity(parent_param_count + param_count);
|
||||
let (total_len, _parent_len, child_len) =
|
||||
def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split());
|
||||
let mut substs = Vec::with_capacity(total_len);
|
||||
// Parent arguments are unknown, except for the receiver type
|
||||
if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) {
|
||||
for param in &parent_generics.params {
|
||||
if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
|
||||
for (_id, param) in parent_generics {
|
||||
if param.name == name::SELF_TYPE {
|
||||
substs.push(receiver_ty.clone());
|
||||
} else {
|
||||
@ -673,7 +676,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
// handle provided type 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 in generic_args.args.iter().take(param_count) {
|
||||
for arg in generic_args.args.iter().take(child_len) {
|
||||
match arg {
|
||||
GenericArg::Type(type_ref) => {
|
||||
let ty = self.make_ty(type_ref);
|
||||
@ -683,10 +686,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
}
|
||||
};
|
||||
let supplied_params = substs.len();
|
||||
for _ in supplied_params..parent_param_count + param_count {
|
||||
for _ in supplied_params..total_len {
|
||||
substs.push(Ty::Unknown);
|
||||
}
|
||||
assert_eq!(substs.len(), parent_param_count + param_count);
|
||||
assert_eq!(substs.len(), total_len);
|
||||
Substs(substs.into())
|
||||
}
|
||||
|
||||
@ -705,11 +708,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
CallableDef::FunctionId(f) => {
|
||||
if let ContainerId::TraitId(trait_) = f.lookup(self.db).container {
|
||||
// construct a TraitDef
|
||||
let substs = a_ty.parameters.prefix(
|
||||
self.db
|
||||
.generic_params(trait_.into())
|
||||
.count_params_including_parent(),
|
||||
);
|
||||
let substs =
|
||||
a_ty.parameters.prefix(generics(self.db, trait_.into()).len());
|
||||
self.obligations.push(Obligation::Trait(TraitRef {
|
||||
trait_: trait_.into(),
|
||||
substs,
|
||||
|
@ -44,8 +44,8 @@ use std::sync::Arc;
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use hir_def::{
|
||||
expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId,
|
||||
GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
|
||||
expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule,
|
||||
Lookup, TraitId, TypeAliasId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use ra_db::{impl_intern_key, salsa, CrateId};
|
||||
@ -53,7 +53,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
primitive::{FloatTy, IntTy, Uncertain},
|
||||
utils::make_mut_slice,
|
||||
utils::{generics, make_mut_slice, Generics},
|
||||
};
|
||||
use display::{HirDisplay, HirFormatter};
|
||||
|
||||
@ -166,16 +166,16 @@ impl TypeCtor {
|
||||
| TypeCtor::Closure { .. } // 1 param representing the signature of the closure
|
||||
=> 1,
|
||||
TypeCtor::Adt(adt) => {
|
||||
let generic_params = db.generic_params(AdtId::from(adt).into());
|
||||
generic_params.count_params_including_parent()
|
||||
let generic_params = generics(db, AdtId::from(adt).into());
|
||||
generic_params.len()
|
||||
}
|
||||
TypeCtor::FnDef(callable) => {
|
||||
let generic_params = db.generic_params(callable.into());
|
||||
generic_params.count_params_including_parent()
|
||||
let generic_params = generics(db, callable.into());
|
||||
generic_params.len()
|
||||
}
|
||||
TypeCtor::AssociatedType(type_alias) => {
|
||||
let generic_params = db.generic_params(type_alias.into());
|
||||
generic_params.count_params_including_parent()
|
||||
let generic_params = generics(db, type_alias.into());
|
||||
generic_params.len()
|
||||
}
|
||||
TypeCtor::FnPtr { num_args } => num_args as usize + 1,
|
||||
TypeCtor::Tuple { cardinality } => cardinality as usize,
|
||||
@ -364,36 +364,26 @@ impl Substs {
|
||||
}
|
||||
|
||||
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
|
||||
pub fn identity(generic_params: &GenericParams) -> Substs {
|
||||
pub(crate) fn identity(generic_params: &Generics) -> Substs {
|
||||
Substs(
|
||||
generic_params
|
||||
.params_including_parent()
|
||||
.into_iter()
|
||||
.map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
|
||||
.collect(),
|
||||
generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Return Substs that replace each parameter by a bound variable.
|
||||
pub fn bound_vars(generic_params: &GenericParams) -> Substs {
|
||||
Substs(
|
||||
generic_params
|
||||
.params_including_parent()
|
||||
.into_iter()
|
||||
.map(|p| Ty::Bound(p.idx))
|
||||
.collect(),
|
||||
)
|
||||
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
|
||||
Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect())
|
||||
}
|
||||
|
||||
pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
|
||||
let def = def.into();
|
||||
let params = db.generic_params(def);
|
||||
let param_count = params.count_params_including_parent();
|
||||
let params = generics(db, def);
|
||||
let param_count = params.len();
|
||||
Substs::builder(param_count)
|
||||
}
|
||||
|
||||
pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
|
||||
Substs::builder(generic_params.count_params_including_parent())
|
||||
pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder {
|
||||
Substs::builder(generic_params.len())
|
||||
}
|
||||
|
||||
pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
|
||||
|
@ -24,7 +24,7 @@ use crate::{
|
||||
db::HirDatabase,
|
||||
primitive::{FloatTy, IntTy},
|
||||
utils::{
|
||||
all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice,
|
||||
all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
|
||||
variant_data,
|
||||
},
|
||||
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
|
||||
@ -111,7 +111,9 @@ impl Ty {
|
||||
Some((it, None)) => it,
|
||||
_ => return None,
|
||||
};
|
||||
if let TypeNs::GenericParam(idx) = resolution {
|
||||
if let TypeNs::GenericParam(param_id) = resolution {
|
||||
let generics = generics(db, resolver.generic_def().expect("generics in scope"));
|
||||
let idx = generics.param_idx(param_id);
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
@ -174,9 +176,11 @@ impl Ty {
|
||||
Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
|
||||
};
|
||||
}
|
||||
TypeNs::GenericParam(idx) => {
|
||||
TypeNs::GenericParam(param_id) => {
|
||||
let generics = generics(db, resolver.generic_def().expect("generics in scope"));
|
||||
let idx = generics.param_idx(param_id);
|
||||
// FIXME: maybe return name in resolution?
|
||||
let name = resolved_segment.name.clone();
|
||||
let name = generics.param_name(param_id);
|
||||
Ty::Param { idx, name }
|
||||
}
|
||||
TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(),
|
||||
@ -315,11 +319,10 @@ pub(super) fn substs_from_path_segment(
|
||||
add_self_param: bool,
|
||||
) -> Substs {
|
||||
let mut substs = Vec::new();
|
||||
let def_generics = def_generic.map(|def| db.generic_params(def.into()));
|
||||
let def_generics = def_generic.map(|def| generics(db, def.into()));
|
||||
|
||||
let (parent_param_count, param_count) =
|
||||
def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len()));
|
||||
substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
|
||||
let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split());
|
||||
substs.extend(iter::repeat(Ty::Unknown).take(parent_len));
|
||||
if add_self_param {
|
||||
// FIXME this add_self_param argument is kind of a hack: Traits have the
|
||||
// Self type as an implicit first type parameter, but it can't be
|
||||
@ -330,8 +333,8 @@ pub(super) fn substs_from_path_segment(
|
||||
if let Some(generic_args) = &segment.args_and_bindings {
|
||||
// if args are provided, it should be all of them, but we can't rely on that
|
||||
let self_param_correction = if add_self_param { 1 } else { 0 };
|
||||
let param_count = param_count - self_param_correction;
|
||||
for arg in generic_args.args.iter().take(param_count) {
|
||||
let child_len = child_len + self_param_correction;
|
||||
for arg in generic_args.args.iter().take(child_len) {
|
||||
match arg {
|
||||
GenericArg::Type(type_ref) => {
|
||||
let ty = Ty::from_hir(db, resolver, type_ref);
|
||||
@ -342,10 +345,10 @@ pub(super) fn substs_from_path_segment(
|
||||
}
|
||||
// add placeholders for args that were not provided
|
||||
let supplied_params = substs.len();
|
||||
for _ in supplied_params..parent_param_count + param_count {
|
||||
for _ in supplied_params..total_len {
|
||||
substs.push(Ty::Unknown);
|
||||
}
|
||||
assert_eq!(substs.len(), parent_param_count + param_count);
|
||||
assert_eq!(substs.len(), total_len);
|
||||
|
||||
// handle defaults
|
||||
if let Some(def_generic) = def_generic {
|
||||
@ -567,12 +570,11 @@ pub(crate) fn generic_predicates_query(
|
||||
/// Resolve the default type params from generics
|
||||
pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs {
|
||||
let resolver = def.resolver(db);
|
||||
let generic_params = db.generic_params(def.into());
|
||||
let generic_params = generics(db, def.into());
|
||||
|
||||
let defaults = generic_params
|
||||
.params_including_parent()
|
||||
.into_iter()
|
||||
.map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
|
||||
.iter()
|
||||
.map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
|
||||
.collect();
|
||||
|
||||
Substs(defaults)
|
||||
@ -589,7 +591,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
|
||||
/// Build the declared type of a function. This should not need to look at the
|
||||
/// function body.
|
||||
fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
|
||||
let generics = db.generic_params(def.into());
|
||||
let generics = generics(db, def.into());
|
||||
let substs = Substs::identity(&generics);
|
||||
Ty::apply(TypeCtor::FnDef(def.into()), substs)
|
||||
}
|
||||
@ -639,7 +641,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
|
||||
if struct_data.variant_data.is_unit() {
|
||||
return type_for_adt(db, def.into()); // Unit struct
|
||||
}
|
||||
let generics = db.generic_params(def.into());
|
||||
let generics = generics(db, def.into());
|
||||
let substs = Substs::identity(&generics);
|
||||
Ty::apply(TypeCtor::FnDef(def.into()), substs)
|
||||
}
|
||||
@ -653,7 +655,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
|
||||
.iter()
|
||||
.map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
|
||||
.collect::<Vec<_>>();
|
||||
let generics = db.generic_params(def.parent.into());
|
||||
let generics = generics(db, def.parent.into());
|
||||
let substs = Substs::identity(&generics);
|
||||
let ret = type_for_adt(db, def.parent.into()).subst(&substs);
|
||||
FnSig::from_params_and_return(params, ret)
|
||||
@ -666,18 +668,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId)
|
||||
if var_data.is_unit() {
|
||||
return type_for_adt(db, def.parent.into()); // Unit variant
|
||||
}
|
||||
let generics = db.generic_params(def.parent.into());
|
||||
let generics = generics(db, def.parent.into());
|
||||
let substs = Substs::identity(&generics);
|
||||
Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
|
||||
}
|
||||
|
||||
fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
|
||||
let generics = db.generic_params(adt.into());
|
||||
let generics = generics(db, adt.into());
|
||||
Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
|
||||
}
|
||||
|
||||
fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
|
||||
let generics = db.generic_params(t.into());
|
||||
let generics = generics(db, t.into());
|
||||
let resolver = t.resolver(db);
|
||||
let type_ref = &db.type_alias_data(t).type_ref;
|
||||
let substs = Substs::identity(&generics);
|
||||
|
@ -19,8 +19,8 @@ use ra_db::{
|
||||
|
||||
use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
|
||||
use crate::{
|
||||
db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs,
|
||||
TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate,
|
||||
ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
/// This represents a trait whose name we could not resolve.
|
||||
@ -547,7 +547,7 @@ pub(crate) fn associated_ty_data_query(
|
||||
ContainerId::TraitId(t) => t,
|
||||
_ => panic!("associated type not in trait"),
|
||||
};
|
||||
let generic_params = db.generic_params(type_alias.into());
|
||||
let generic_params = generics(db, type_alias.into());
|
||||
let bound_data = chalk_rust_ir::AssociatedTyDatumBound {
|
||||
// FIXME add bounds and where clauses
|
||||
bounds: vec![],
|
||||
@ -557,7 +557,7 @@ pub(crate) fn associated_ty_data_query(
|
||||
trait_id: trait_.to_chalk(db),
|
||||
id,
|
||||
name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()),
|
||||
binders: make_binders(bound_data, generic_params.count_params_including_parent()),
|
||||
binders: make_binders(bound_data, generic_params.len()),
|
||||
};
|
||||
Arc::new(datum)
|
||||
}
|
||||
@ -589,7 +589,7 @@ pub(crate) fn trait_datum_query(
|
||||
let trait_: TraitId = from_chalk(db, trait_id);
|
||||
let trait_data = db.trait_data(trait_);
|
||||
debug!("trait {:?} = {:?}", trait_id, trait_data.name);
|
||||
let generic_params = db.generic_params(trait_.into());
|
||||
let generic_params = generics(db, trait_.into());
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let flags = chalk_rust_ir::TraitFlags {
|
||||
auto: trait_data.auto,
|
||||
@ -626,7 +626,7 @@ pub(crate) fn struct_datum_query(
|
||||
let where_clauses = type_ctor
|
||||
.as_generic_def()
|
||||
.map(|generic_def| {
|
||||
let generic_params = db.generic_params(generic_def.into());
|
||||
let generic_params = generics(db, generic_def.into());
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
convert_where_clauses(db, generic_def, &bound_vars)
|
||||
})
|
||||
@ -669,7 +669,7 @@ fn impl_block_datum(
|
||||
let trait_ref = db.impl_trait(impl_id)?;
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
|
||||
let generic_params = db.generic_params(impl_id.into());
|
||||
let generic_params = generics(db, impl_id.into());
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let trait_ref = trait_ref.subst(&bound_vars);
|
||||
let trait_ = trait_ref.trait_;
|
||||
@ -767,7 +767,7 @@ fn type_alias_associated_ty_value(
|
||||
.trait_data(trait_ref.trait_)
|
||||
.associated_type_by_name(&type_alias_data.name)
|
||||
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
||||
let generic_params = db.generic_params(impl_id.into());
|
||||
let generic_params = generics(db, impl_id.into());
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let ty = db.ty(type_alias.into()).subst(&bound_vars);
|
||||
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
|
||||
|
@ -5,9 +5,10 @@ use std::sync::Arc;
|
||||
use hir_def::{
|
||||
adt::VariantData,
|
||||
db::DefDatabase,
|
||||
generics::{GenericParamData, GenericParams},
|
||||
resolver::{HasResolver, TypeNs},
|
||||
type_ref::TypeRef,
|
||||
TraitId, TypeAliasId, VariantId,
|
||||
ContainerId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::{self, Name};
|
||||
|
||||
@ -82,3 +83,83 @@ pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
|
||||
}
|
||||
Arc::get_mut(a).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn generics(db: &impl DefDatabase, def: GenericDefId) -> Generics {
|
||||
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
||||
Generics { def, params: db.generic_params(def), parent_generics }
|
||||
}
|
||||
|
||||
pub(crate) struct Generics {
|
||||
def: GenericDefId,
|
||||
pub(crate) params: Arc<GenericParams>,
|
||||
parent_generics: Option<Box<Generics>>,
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a {
|
||||
self.parent_generics
|
||||
.as_ref()
|
||||
.into_iter()
|
||||
.flat_map(|it| it.params.params.iter())
|
||||
.chain(self.params.params.iter())
|
||||
.enumerate()
|
||||
.map(|(i, (_local_id, p))| (i as u32, p))
|
||||
}
|
||||
|
||||
pub(crate) fn iter_parent<'a>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a {
|
||||
self.parent_generics
|
||||
.as_ref()
|
||||
.into_iter()
|
||||
.flat_map(|it| it.params.params.iter())
|
||||
.enumerate()
|
||||
.map(|(i, (_local_id, p))| (i as u32, p))
|
||||
}
|
||||
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.len_split().0
|
||||
}
|
||||
/// (total, parents, child)
|
||||
pub(crate) fn len_split(&self) -> (usize, usize, usize) {
|
||||
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
|
||||
let child = self.params.params.len();
|
||||
(parent + child, parent, child)
|
||||
}
|
||||
pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 {
|
||||
self.find_param(param).0
|
||||
}
|
||||
pub(crate) fn param_name(&self, param: GenericParamId) -> Name {
|
||||
self.find_param(param).1.name.clone()
|
||||
}
|
||||
fn find_param(&self, param: GenericParamId) -> (u32, &GenericParamData) {
|
||||
if param.parent == self.def {
|
||||
let (idx, (_local_id, data)) = self
|
||||
.params
|
||||
.params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||
.unwrap();
|
||||
let (_total, parent_len, _child) = self.len_split();
|
||||
return ((parent_len + idx) as u32, data);
|
||||
}
|
||||
self.parent_generics.as_ref().unwrap().find_param(param)
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
|
||||
let container = match def {
|
||||
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
||||
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
||||
GenericDefId::ConstId(it) => it.lookup(db).container,
|
||||
GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
|
||||
GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
|
||||
};
|
||||
|
||||
match container {
|
||||
ContainerId::ImplId(it) => Some(it.into()),
|
||||
ContainerId::TraitId(it) => Some(it.into()),
|
||||
ContainerId::ModuleId(_) => None,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user