Merge #1923
1923: Add SubstsBuilder r=flodiebold a=flodiebold + further refactoring. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
fc218ec0d0
@ -339,10 +339,14 @@ pub struct Struct {
|
||||
}
|
||||
|
||||
impl Struct {
|
||||
pub fn module(self, db: &impl HirDatabase) -> Module {
|
||||
pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||
self.module(db).krate(db)
|
||||
}
|
||||
|
||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||
db.struct_data(self).name.clone()
|
||||
}
|
||||
@ -423,10 +427,14 @@ pub struct Enum {
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
pub fn module(self, db: &impl HirDatabase) -> Module {
|
||||
pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||
self.module(db).krate(db)
|
||||
}
|
||||
|
||||
pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
|
||||
db.enum_data(self).name.clone()
|
||||
}
|
||||
@ -514,7 +522,7 @@ impl Adt {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
|
||||
pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
|
||||
match self {
|
||||
Adt::Struct(s) => s.module(db),
|
||||
Adt::Union(s) => s.module(db),
|
||||
|
@ -9,7 +9,6 @@ test_utils::marks!(
|
||||
glob_across_crates
|
||||
std_prelude
|
||||
match_ergonomics_ref
|
||||
trait_resolution_on_fn_type
|
||||
infer_while_let
|
||||
macro_rules_from_other_crates_are_visible_with_macro_use
|
||||
prelude_is_macro_use
|
||||
|
@ -14,11 +14,11 @@ pub(crate) mod display;
|
||||
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, mem};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name,
|
||||
Trait, TypeAlias,
|
||||
db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams,
|
||||
HasGenericParams, Name, Trait, TypeAlias,
|
||||
};
|
||||
use display::{HirDisplay, HirFormatter};
|
||||
|
||||
@ -111,6 +111,81 @@ pub enum TypeCtor {
|
||||
Closure { def: DefWithBody, expr: ExprId },
|
||||
}
|
||||
|
||||
impl TypeCtor {
|
||||
pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
|
||||
match self {
|
||||
TypeCtor::Bool
|
||||
| TypeCtor::Char
|
||||
| TypeCtor::Int(_)
|
||||
| TypeCtor::Float(_)
|
||||
| TypeCtor::Str
|
||||
| TypeCtor::Never => 0,
|
||||
TypeCtor::Slice
|
||||
| TypeCtor::Array
|
||||
| TypeCtor::RawPtr(_)
|
||||
| TypeCtor::Ref(_)
|
||||
| TypeCtor::Closure { .. } // 1 param representing the signature of the closure
|
||||
=> 1,
|
||||
TypeCtor::Adt(adt) => {
|
||||
let generic_params = adt.generic_params(db);
|
||||
generic_params.count_params_including_parent()
|
||||
}
|
||||
TypeCtor::FnDef(callable) => {
|
||||
let generic_params = callable.generic_params(db);
|
||||
generic_params.count_params_including_parent()
|
||||
}
|
||||
TypeCtor::AssociatedType(type_alias) => {
|
||||
let generic_params = type_alias.generic_params(db);
|
||||
generic_params.count_params_including_parent()
|
||||
}
|
||||
TypeCtor::FnPtr { num_args } => num_args as usize + 1,
|
||||
TypeCtor::Tuple { cardinality } => cardinality as usize,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
|
||||
match self {
|
||||
TypeCtor::Bool
|
||||
| TypeCtor::Char
|
||||
| TypeCtor::Int(_)
|
||||
| TypeCtor::Float(_)
|
||||
| TypeCtor::Str
|
||||
| TypeCtor::Never
|
||||
| TypeCtor::Slice
|
||||
| TypeCtor::Array
|
||||
| TypeCtor::RawPtr(_)
|
||||
| TypeCtor::Ref(_)
|
||||
| TypeCtor::FnPtr { .. }
|
||||
| TypeCtor::Tuple { .. } => None,
|
||||
TypeCtor::Closure { def, .. } => def.krate(db),
|
||||
TypeCtor::Adt(adt) => adt.krate(db),
|
||||
TypeCtor::FnDef(callable) => callable.krate(db),
|
||||
TypeCtor::AssociatedType(type_alias) => type_alias.krate(db),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_generic_def(self) -> Option<crate::generics::GenericDef> {
|
||||
match self {
|
||||
TypeCtor::Bool
|
||||
| TypeCtor::Char
|
||||
| TypeCtor::Int(_)
|
||||
| TypeCtor::Float(_)
|
||||
| TypeCtor::Str
|
||||
| TypeCtor::Never
|
||||
| TypeCtor::Slice
|
||||
| TypeCtor::Array
|
||||
| TypeCtor::RawPtr(_)
|
||||
| TypeCtor::Ref(_)
|
||||
| TypeCtor::FnPtr { .. }
|
||||
| TypeCtor::Tuple { .. }
|
||||
| TypeCtor::Closure { .. } => None,
|
||||
TypeCtor::Adt(adt) => Some(adt.into()),
|
||||
TypeCtor::FnDef(callable) => Some(callable.into()),
|
||||
TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A nominal type with (maybe 0) type parameters. This might be a primitive
|
||||
/// type like `bool`, a struct, tuple, function pointer, reference or
|
||||
/// several other things.
|
||||
@ -271,11 +346,65 @@ impl Substs {
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build_for_def(
|
||||
db: &impl HirDatabase,
|
||||
def: impl crate::HasGenericParams,
|
||||
) -> SubstsBuilder {
|
||||
let params = def.generic_params(db);
|
||||
let param_count = params.count_params_including_parent();
|
||||
Substs::builder(param_count)
|
||||
}
|
||||
|
||||
pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
|
||||
Substs::builder(generic_params.count_params_including_parent())
|
||||
}
|
||||
|
||||
pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
|
||||
Substs::builder(type_ctor.num_ty_params(db))
|
||||
}
|
||||
|
||||
fn builder(param_count: usize) -> SubstsBuilder {
|
||||
SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Ty>> for Substs {
|
||||
fn from(v: Vec<Ty>) -> Self {
|
||||
Substs(v.into())
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubstsBuilder {
|
||||
vec: Vec<Ty>,
|
||||
param_count: usize,
|
||||
}
|
||||
|
||||
impl SubstsBuilder {
|
||||
pub fn build(self) -> Substs {
|
||||
assert_eq!(self.vec.len(), self.param_count);
|
||||
Substs(self.vec.into())
|
||||
}
|
||||
|
||||
pub fn push(mut self, ty: Ty) -> Self {
|
||||
self.vec.push(ty);
|
||||
self
|
||||
}
|
||||
|
||||
fn remaining(&self) -> usize {
|
||||
self.param_count - self.vec.len()
|
||||
}
|
||||
|
||||
pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self {
|
||||
self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn fill_with_unknown(mut self) -> Self {
|
||||
self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self {
|
||||
assert!(self.vec.is_empty());
|
||||
assert!(parent_substs.len() <= self.param_count);
|
||||
self.vec.extend(parent_substs.iter().cloned());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use std::iter::successors;
|
||||
|
||||
use log::{info, warn};
|
||||
|
||||
use super::{traits::Solution, Canonical, Ty, TypeWalk};
|
||||
use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
|
||||
use crate::{db::HirDatabase, name, HasGenericParams, Resolver};
|
||||
|
||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||
@ -44,7 +44,8 @@ fn deref_by_trait(
|
||||
};
|
||||
let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
|
||||
|
||||
if target.generic_params(db).count_params_including_parent() != 1 {
|
||||
let generic_params = target.generic_params(db);
|
||||
if generic_params.count_params_including_parent() != 1 {
|
||||
// the Target type + Deref trait should only have one generic parameter,
|
||||
// namely Deref's Self type
|
||||
return None;
|
||||
@ -54,12 +55,13 @@ fn deref_by_trait(
|
||||
|
||||
let env = super::lower::trait_env(db, resolver);
|
||||
|
||||
let parameters = Substs::build_for_generics(&generic_params)
|
||||
.push(ty.value.clone().shift_bound_vars(1))
|
||||
.build();
|
||||
|
||||
let projection = super::traits::ProjectionPredicate {
|
||||
ty: Ty::Bound(0),
|
||||
projection_ty: super::ProjectionTy {
|
||||
associated_ty: target,
|
||||
parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
|
||||
},
|
||||
projection_ty: super::ProjectionTy { associated_ty: target, parameters },
|
||||
};
|
||||
|
||||
let obligation = super::Obligation::Projection(projection);
|
||||
|
@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
};
|
||||
let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
|
||||
|
||||
let inner_tys: Substs = args
|
||||
let inner_tys = args
|
||||
.iter()
|
||||
.zip(expectations_iter)
|
||||
.map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
.collect();
|
||||
|
||||
Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys)
|
||||
Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
|
||||
}
|
||||
Pat::Ref { pat, mutability } => {
|
||||
let expectation = match expected.as_reference() {
|
||||
@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ty: pat_ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: into_iter_item_alias,
|
||||
parameters: vec![iterable_ty].into(),
|
||||
parameters: Substs::single(iterable_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
sig_tys.push(ret_ty.clone());
|
||||
let sig_ty = Ty::apply(
|
||||
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
|
||||
sig_tys.into(),
|
||||
Substs(sig_tys.into()),
|
||||
);
|
||||
let closure_ty = Ty::apply_one(
|
||||
TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
|
||||
@ -1400,7 +1399,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ty: ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: future_future_output_alias,
|
||||
parameters: vec![inner_ty].into(),
|
||||
parameters: Substs::single(inner_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
@ -1419,7 +1418,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ty: ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: ops_try_ok_alias,
|
||||
parameters: vec![inner_ty].into(),
|
||||
parameters: Substs::single(inner_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
|
@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
AssocItem::Const(c) => ValueNs::Const(c),
|
||||
AssocItem::TypeAlias(_) => unreachable!(),
|
||||
};
|
||||
let generics = item.generic_params(self.db);
|
||||
let mut substs = Vec::with_capacity(generics.count_params_including_parent());
|
||||
substs.extend(trait_ref.substs.iter().cloned());
|
||||
substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len()));
|
||||
let substs = Substs::build_for_def(self.db, item)
|
||||
.use_parent_substs(&trait_ref.substs)
|
||||
.fill_with_unknown()
|
||||
.build();
|
||||
|
||||
self.write_assoc_resolution(id, item);
|
||||
Some((def, Some(substs.into())))
|
||||
Some((def, Some(substs)))
|
||||
}
|
||||
|
||||
fn resolve_ty_assoc_item(
|
||||
|
@ -3,7 +3,8 @@
|
||||
use super::{InferenceContext, Obligation};
|
||||
use crate::db::HirDatabase;
|
||||
use crate::ty::{
|
||||
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk,
|
||||
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
|
||||
TypeWalk,
|
||||
};
|
||||
|
||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
@ -74,12 +75,9 @@ where
|
||||
}
|
||||
|
||||
fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef {
|
||||
let substs = trait_ref
|
||||
.substs
|
||||
.iter()
|
||||
.map(|ty| self.do_canonicalize_ty(ty.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
TraitRef { trait_: trait_ref.trait_, substs: substs.into() }
|
||||
let substs =
|
||||
trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
|
||||
TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) }
|
||||
}
|
||||
|
||||
fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
|
||||
@ -90,12 +88,9 @@ where
|
||||
}
|
||||
|
||||
fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy {
|
||||
let params = projection_ty
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|ty| self.do_canonicalize_ty(ty.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() }
|
||||
let params =
|
||||
projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
|
||||
ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) }
|
||||
}
|
||||
|
||||
fn do_canonicalize_projection_predicate(
|
||||
@ -153,8 +148,7 @@ impl<T> Canonicalized<T> {
|
||||
solution: Canonical<Vec<Ty>>,
|
||||
) {
|
||||
// the solution may contain new variables, which we need to convert to new inference vars
|
||||
let new_vars =
|
||||
(0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into();
|
||||
let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect());
|
||||
for (i, ty) in solution.value.into_iter().enumerate() {
|
||||
let var = self.free_vars[i];
|
||||
ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
|
||||
|
@ -239,14 +239,10 @@ impl Ty {
|
||||
let traits = traits_from_env.flat_map(|t| t.all_super_traits(db));
|
||||
for t in traits {
|
||||
if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
|
||||
let generics = t.generic_params(db);
|
||||
let mut substs = Vec::new();
|
||||
substs.push(self_ty.clone());
|
||||
substs.extend(
|
||||
iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1),
|
||||
);
|
||||
let substs =
|
||||
Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build();
|
||||
// FIXME handle type parameters on the segment
|
||||
return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() });
|
||||
return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
|
||||
}
|
||||
}
|
||||
Ty::Unknown
|
||||
@ -766,6 +762,16 @@ pub enum CallableDef {
|
||||
}
|
||||
impl_froms!(CallableDef: Function, Struct, EnumVariant);
|
||||
|
||||
impl CallableDef {
|
||||
pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> {
|
||||
match self {
|
||||
CallableDef::Function(f) => f.krate(db),
|
||||
CallableDef::Struct(s) => s.krate(db),
|
||||
CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CallableDef> for GenericDef {
|
||||
fn from(def: CallableDef) -> GenericDef {
|
||||
match def {
|
||||
|
@ -10,7 +10,6 @@ use rustc_hash::FxHashMap;
|
||||
use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
generics::HasGenericParams,
|
||||
impl_block::{ImplBlock, ImplId},
|
||||
nameres::CrateModuleId,
|
||||
resolve::Resolver,
|
||||
@ -331,20 +330,13 @@ fn generic_implements_goal(
|
||||
trait_: Trait,
|
||||
self_ty: Canonical<Ty>,
|
||||
) -> Canonical<InEnvironment<super::Obligation>> {
|
||||
let mut substs = Vec::new();
|
||||
let generics = trait_.generic_params(db);
|
||||
let num_vars = self_ty.num_vars;
|
||||
substs.push(self_ty.value);
|
||||
substs.extend(
|
||||
generics
|
||||
.params_including_parent()
|
||||
.into_iter()
|
||||
.skip(1)
|
||||
.enumerate()
|
||||
.map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
|
||||
);
|
||||
let substs = super::Substs::build_for_def(db, trait_)
|
||||
.push(self_ty.value)
|
||||
.fill_with_bound_vars(num_vars as u32)
|
||||
.build();
|
||||
let num_vars = substs.len() - 1 + self_ty.num_vars;
|
||||
let trait_ref = TraitRef { trait_, substs: substs.into() };
|
||||
let trait_ref = TraitRef { trait_, substs };
|
||||
let obligation = super::Obligation::Trait(trait_ref);
|
||||
Canonical { num_vars, value: InEnvironment::new(env, obligation) }
|
||||
}
|
||||
|
@ -3321,7 +3321,6 @@ fn test() { S2.into()<|>; }
|
||||
|
||||
#[test]
|
||||
fn method_resolution_encountering_fn_type() {
|
||||
covers!(trait_resolution_on_fn_type);
|
||||
type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
|
@ -10,17 +10,13 @@ use chalk_ir::{
|
||||
use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
|
||||
|
||||
use ra_db::salsa::{InternId, InternKey};
|
||||
use test_utils::tested_by;
|
||||
|
||||
use super::{Canonical, ChalkContext, Impl, Obligation};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
generics::GenericDef,
|
||||
ty::display::HirDisplay,
|
||||
ty::{
|
||||
ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
||||
TypeWalk,
|
||||
},
|
||||
ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
|
||||
AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
|
||||
};
|
||||
|
||||
@ -124,14 +120,15 @@ impl ToChalk for Substs {
|
||||
}
|
||||
|
||||
fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs {
|
||||
parameters
|
||||
let tys = parameters
|
||||
.into_iter()
|
||||
.map(|p| match p {
|
||||
chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
|
||||
chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
.into();
|
||||
Substs(tys)
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query(
|
||||
struct_id: chalk_ir::StructId,
|
||||
) -> Arc<StructDatum> {
|
||||
debug!("struct_datum {:?}", struct_id);
|
||||
let type_ctor = from_chalk(db, struct_id);
|
||||
let type_ctor: TypeCtor = from_chalk(db, struct_id);
|
||||
debug!("struct {:?} = {:?}", struct_id, type_ctor);
|
||||
// FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
|
||||
// FIXME extract this to a method on Ty
|
||||
let (num_params, where_clauses, upstream) = match type_ctor {
|
||||
TypeCtor::Bool
|
||||
| TypeCtor::Char
|
||||
| TypeCtor::Int(_)
|
||||
| TypeCtor::Float(_)
|
||||
| TypeCtor::Never
|
||||
| TypeCtor::Str => (0, vec![], true),
|
||||
TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
|
||||
(1, vec![], true)
|
||||
}
|
||||
TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
|
||||
TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
|
||||
TypeCtor::FnDef(callable) => {
|
||||
tested_by!(trait_resolution_on_fn_type);
|
||||
let upstream = match callable {
|
||||
CallableDef::Function(f) => f.module(db).krate(db),
|
||||
CallableDef::Struct(s) => s.module(db).krate(db),
|
||||
CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
|
||||
} != Some(krate);
|
||||
let generic_def: GenericDef = callable.into();
|
||||
let num_params = type_ctor.num_ty_params(db);
|
||||
let upstream = type_ctor.krate(db) != Some(krate);
|
||||
let where_clauses = type_ctor
|
||||
.as_generic_def()
|
||||
.map(|generic_def| {
|
||||
let generic_params = generic_def.generic_params(db);
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
|
||||
(generic_params.count_params_including_parent(), where_clauses, upstream)
|
||||
}
|
||||
TypeCtor::Adt(adt) => {
|
||||
let generic_params = adt.generic_params(db);
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
|
||||
(
|
||||
generic_params.count_params_including_parent(),
|
||||
where_clauses,
|
||||
adt.krate(db) != Some(krate),
|
||||
)
|
||||
}
|
||||
TypeCtor::AssociatedType(type_alias) => {
|
||||
let generic_params = type_alias.generic_params(db);
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
|
||||
(
|
||||
generic_params.count_params_including_parent(),
|
||||
where_clauses,
|
||||
type_alias.krate(db) != Some(krate),
|
||||
)
|
||||
}
|
||||
TypeCtor::Closure { def, .. } => {
|
||||
let upstream = def.krate(db) != Some(krate);
|
||||
(1, vec![], upstream)
|
||||
}
|
||||
};
|
||||
convert_where_clauses(db, generic_def, &bound_vars)
|
||||
})
|
||||
.unwrap_or_else(Vec::new);
|
||||
let flags = chalk_rust_ir::StructFlags {
|
||||
upstream,
|
||||
// FIXME set fundamental flag correctly
|
||||
@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum(
|
||||
|
||||
let arg_ty = Ty::apply(
|
||||
TypeCtor::Tuple { cardinality: num_args },
|
||||
(0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(),
|
||||
Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
|
||||
);
|
||||
let output_ty = Ty::Bound(num_args.into());
|
||||
let sig_ty = Ty::apply(
|
||||
TypeCtor::FnPtr { num_args },
|
||||
(0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(),
|
||||
Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
|
||||
);
|
||||
|
||||
let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
|
||||
|
||||
let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() };
|
||||
let trait_ref = TraitRef {
|
||||
trait_,
|
||||
substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
|
||||
};
|
||||
|
||||
let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user