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