rustc: move defaulting's use of &mut Substs from InferCtxt to typeck.
This commit is contained in:
parent
c87063f07e
commit
5ef6af09e3
12 changed files with 212 additions and 231 deletions
|
@ -1172,15 +1172,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx.mk_var(self.next_ty_var_id(false))
|
self.tcx.mk_var(self.next_ty_var_id(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_with_default(&self,
|
|
||||||
default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
|
|
||||||
let ty_var_id = self.type_variables
|
|
||||||
.borrow_mut()
|
|
||||||
.new_var(false, default);
|
|
||||||
|
|
||||||
self.tcx.mk_var(ty_var_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
|
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
|
||||||
self.tcx.mk_var(self.next_ty_var_id(true))
|
self.tcx.mk_var(self.next_ty_var_id(true))
|
||||||
}
|
}
|
||||||
|
@ -1205,35 +1196,49 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
ty::ReVar(self.region_vars.new_region_var(origin))
|
ty::ReVar(self.region_vars.new_region_var(origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a region inference variable for the given
|
||||||
|
/// region parameter definition.
|
||||||
|
pub fn region_var_for_def(&self,
|
||||||
|
span: Span,
|
||||||
|
def: &ty::RegionParameterDef)
|
||||||
|
-> ty::Region {
|
||||||
|
self.next_region_var(EarlyBoundRegion(span, def.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a type inference variable for the given
|
||||||
|
/// type parameter definition. The substitutions are
|
||||||
|
/// for actual parameters that may be referred to by
|
||||||
|
/// the default of this type parameter, if it exists.
|
||||||
|
/// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
|
||||||
|
/// used in a path such as `Foo::<T, U>::new()` will
|
||||||
|
/// use an inference variable for `C` with `[T, U]`
|
||||||
|
/// as the substitutions for the default, `(T, U)`.
|
||||||
|
pub fn type_var_for_def(&self,
|
||||||
|
span: Span,
|
||||||
|
def: &ty::TypeParameterDef<'tcx>,
|
||||||
|
substs: &Substs<'tcx>)
|
||||||
|
-> Ty<'tcx> {
|
||||||
|
let default = def.default.map(|default| {
|
||||||
|
type_variable::Default {
|
||||||
|
ty: default.subst_spanned(self.tcx, substs, Some(span)),
|
||||||
|
origin_span: span,
|
||||||
|
def_id: def.default_def_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let ty_var_id = self.type_variables
|
||||||
|
.borrow_mut()
|
||||||
|
.new_var(false, default);
|
||||||
|
|
||||||
|
self.tcx.mk_var(ty_var_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn region_vars_for_defs(&self,
|
pub fn region_vars_for_defs(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
defs: &[ty::RegionParameterDef])
|
defs: &[ty::RegionParameterDef])
|
||||||
-> Vec<ty::Region> {
|
-> Vec<ty::Region> {
|
||||||
defs.iter()
|
defs.iter().map(|def| self.region_var_for_def(span, def)).collect()
|
||||||
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have to take `&mut Substs` in order to provide the correct substitutions for defaults
|
|
||||||
// along the way, for this reason we don't return them.
|
|
||||||
pub fn type_vars_for_defs(&self,
|
|
||||||
span: Span,
|
|
||||||
space: subst::ParamSpace,
|
|
||||||
substs: &mut Substs<'tcx>,
|
|
||||||
defs: &[ty::TypeParameterDef<'tcx>]) {
|
|
||||||
|
|
||||||
for def in defs.iter() {
|
|
||||||
let default = def.default.map(|default| {
|
|
||||||
type_variable::Default {
|
|
||||||
ty: default.subst_spanned(self.tcx, substs, Some(span)),
|
|
||||||
origin_span: span,
|
|
||||||
def_id: def.default_def_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let ty_var = self.next_ty_var_with_default(default);
|
|
||||||
substs.types.push(space, ty_var);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
||||||
|
@ -1243,21 +1248,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
generics: &ty::Generics<'tcx>)
|
generics: &ty::Generics<'tcx>)
|
||||||
-> &'tcx subst::Substs<'tcx>
|
-> &'tcx subst::Substs<'tcx>
|
||||||
{
|
{
|
||||||
let type_params = subst::VecPerParamSpace::empty();
|
let type_defs = generics.types.as_full_slice();
|
||||||
|
let region_defs = generics.regions.as_full_slice();
|
||||||
let region_params =
|
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||||
generics.regions.map(
|
self.region_var_for_def(span, def)
|
||||||
|d| self.next_region_var(EarlyBoundRegion(span, d.name)));
|
}, |def, substs| {
|
||||||
|
self.type_var_for_def(span, def, substs)
|
||||||
let mut substs = subst::Substs::new(type_params, region_params);
|
});
|
||||||
|
|
||||||
for space in subst::ParamSpace::all().iter() {
|
|
||||||
self.type_vars_for_defs(
|
|
||||||
span,
|
|
||||||
*space,
|
|
||||||
&mut substs,
|
|
||||||
generics.types.get_slice(*space));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tcx.mk_substs(substs)
|
self.tcx.mk_substs(substs)
|
||||||
}
|
}
|
||||||
|
@ -1269,25 +1266,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics<'tcx>,
|
||||||
self_ty: Ty<'tcx>)
|
self_ty: Ty<'tcx>)
|
||||||
-> subst::Substs<'tcx>
|
-> &'tcx subst::Substs<'tcx>
|
||||||
{
|
{
|
||||||
|
|
||||||
assert!(generics.types.len(subst::SelfSpace) == 1);
|
assert!(generics.types.len(subst::SelfSpace) == 1);
|
||||||
assert!(generics.types.len(subst::FnSpace) == 0);
|
assert!(generics.types.len(subst::FnSpace) == 0);
|
||||||
assert!(generics.regions.len(subst::SelfSpace) == 0);
|
|
||||||
assert!(generics.regions.len(subst::FnSpace) == 0);
|
|
||||||
|
|
||||||
let type_params = Vec::new();
|
let type_defs = generics.types.as_full_slice();
|
||||||
|
let region_defs = generics.regions.as_full_slice();
|
||||||
|
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||||
|
self.region_var_for_def(span, def)
|
||||||
|
}, |def, substs| {
|
||||||
|
if def.space == subst::SelfSpace {
|
||||||
|
self_ty
|
||||||
|
} else {
|
||||||
|
self.type_var_for_def(span, def, substs)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
|
self.tcx.mk_substs(substs)
|
||||||
let regions = self.region_vars_for_defs(span, region_param_defs);
|
|
||||||
|
|
||||||
let mut substs = subst::Substs::new_trait(type_params, regions, self_ty);
|
|
||||||
|
|
||||||
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
|
|
||||||
self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs);
|
|
||||||
|
|
||||||
return substs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
|
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
|
||||||
|
|
|
@ -31,7 +31,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||||
use ty::error::ExpectedFound;
|
use ty::error::ExpectedFound;
|
||||||
use ty::fast_reject;
|
use ty::fast_reject;
|
||||||
use ty::fold::TypeFolder;
|
use ty::fold::TypeFolder;
|
||||||
use ty::subst::{self, Subst, TypeSpace};
|
use ty::subst::{Subst, TypeSpace};
|
||||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -167,27 +167,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_substs(&self,
|
|
||||||
did: DefId,
|
|
||||||
obligation: PredicateObligation<'tcx>)
|
|
||||||
-> subst::Substs<'tcx> {
|
|
||||||
let tcx = self.tcx;
|
|
||||||
|
|
||||||
let ity = tcx.lookup_item_type(did);
|
|
||||||
let (tps, rps, _) =
|
|
||||||
(ity.generics.types.get_slice(TypeSpace),
|
|
||||||
ity.generics.regions.get_slice(TypeSpace),
|
|
||||||
ity.ty);
|
|
||||||
|
|
||||||
let rps = self.region_vars_for_defs(obligation.cause.span, rps);
|
|
||||||
let mut substs = subst::Substs::new_type(vec![], rps);
|
|
||||||
self.type_vars_for_defs(obligation.cause.span,
|
|
||||||
TypeSpace,
|
|
||||||
&mut substs,
|
|
||||||
tps);
|
|
||||||
substs
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
||||||
/// returns the fuzzy category of a given type, or None
|
/// returns the fuzzy category of a given type, or None
|
||||||
/// if the type can be equated to any type.
|
/// if the type can be equated to any type.
|
||||||
|
@ -242,10 +221,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
self.tcx.lookup_trait_def(trait_ref.def_id)
|
self.tcx.lookup_trait_def(trait_ref.def_id)
|
||||||
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
|
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
|
||||||
|
let ity = tcx.lookup_item_type(def_id);
|
||||||
|
let impl_substs = self.fresh_substs_for_generics(obligation.cause.span,
|
||||||
|
&ity.generics);
|
||||||
let impl_trait_ref = tcx
|
let impl_trait_ref = tcx
|
||||||
.impl_trait_ref(def_id)
|
.impl_trait_ref(def_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.subst(tcx, &self.impl_substs(def_id, obligation.clone()));
|
.subst(tcx, impl_substs);
|
||||||
|
|
||||||
let impl_self_ty = impl_trait_ref.self_ty();
|
let impl_self_ty = impl_trait_ref.self_ty();
|
||||||
|
|
||||||
|
|
|
@ -358,8 +358,7 @@ pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
|
||||||
impl_def_id: DefId)
|
impl_def_id: DefId)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx>
|
||||||
{
|
{
|
||||||
let tcx = infcx.tcx;
|
let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).generics;
|
||||||
let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
|
|
||||||
infcx.fresh_substs_for_generics(span, &impl_generics)
|
infcx.fresh_substs_for_generics(span, &impl_generics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,33 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a Substs for generic parameter definitions,
|
||||||
|
/// by calling closures to obtain each region and type.
|
||||||
|
/// The closures get to observe the Substs as they're
|
||||||
|
/// being built, which can be used to correctly
|
||||||
|
/// substitute defaults of type parameters.
|
||||||
|
pub fn from_generics<FR, FT>(generics: &ty::Generics<'tcx>,
|
||||||
|
mut mk_region: FR,
|
||||||
|
mut mk_type: FT)
|
||||||
|
-> Substs<'tcx>
|
||||||
|
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
|
||||||
|
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
|
||||||
|
let mut substs = Substs::empty();
|
||||||
|
for &space in &ParamSpace::all() {
|
||||||
|
for def in generics.regions.get_slice(space) {
|
||||||
|
let region = mk_region(def, &substs);
|
||||||
|
assert_eq!(substs.regions.len(def.space), def.index as usize);
|
||||||
|
substs.regions.push(def.space, region);
|
||||||
|
}
|
||||||
|
for def in generics.types.get_slice(space) {
|
||||||
|
let ty = mk_type(def, &substs);
|
||||||
|
assert_eq!(substs.types.len(def.space), def.index as usize);
|
||||||
|
substs.types.push(def.space, ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
substs
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_noop(&self) -> bool {
|
pub fn is_noop(&self) -> bool {
|
||||||
self.regions.is_empty() && self.types.is_empty()
|
self.regions.is_empty() && self.types.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -81,6 +108,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||||
*self.types.get(ty_param_def.space, ty_param_def.index as usize)
|
*self.types.get(ty_param_def.space, ty_param_def.index as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region {
|
||||||
|
*self.regions.get(def.space, def.index as usize)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
||||||
self.types.get_self().cloned()
|
self.types.get_self().cloned()
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ use hir::def_id::DefId;
|
||||||
use hir::print as pprust;
|
use hir::print as pprust;
|
||||||
use middle::resolve_lifetime as rl;
|
use middle::resolve_lifetime as rl;
|
||||||
use rustc::lint;
|
use rustc::lint;
|
||||||
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
|
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||||
use rustc::ty::wf::object_region_bounds;
|
use rustc::ty::wf::object_region_bounds;
|
||||||
|
@ -115,11 +115,15 @@ pub trait AstConv<'gcx, 'tcx> {
|
||||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
|
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
|
||||||
|
|
||||||
/// What type should we use when a type is omitted?
|
/// What type should we use when a type is omitted?
|
||||||
fn ty_infer(&self,
|
fn ty_infer(&self, span: Span) -> Ty<'tcx>;
|
||||||
param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
|
|
||||||
substs: Option<&mut Substs<'tcx>>,
|
/// Same as ty_infer, but with a known type parameter definition.
|
||||||
space: Option<ParamSpace>,
|
fn ty_infer_for_def(&self,
|
||||||
span: Span) -> Ty<'tcx>;
|
_def: &ty::TypeParameterDef<'tcx>,
|
||||||
|
_substs: &Substs<'tcx>,
|
||||||
|
span: Span) -> Ty<'tcx> {
|
||||||
|
self.ty_infer(span)
|
||||||
|
}
|
||||||
|
|
||||||
/// Projecting an associated type from a (potentially)
|
/// Projecting an associated type from a (potentially)
|
||||||
/// higher-ranked trait reference is more complicated, because of
|
/// higher-ranked trait reference is more complicated, because of
|
||||||
|
@ -535,26 +539,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
self_ty: Option<Ty<'tcx>>)
|
self_ty: Option<Ty<'tcx>>)
|
||||||
-> Vec<Ty<'tcx>>
|
-> Vec<Ty<'tcx>>
|
||||||
{
|
{
|
||||||
fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
|
let use_default = |p: &ty::TypeParameterDef<'tcx>| {
|
||||||
-> Option<ty::TypeParameterDef<'tcx>>
|
|
||||||
{
|
|
||||||
if let Some(ref default) = p.default {
|
if let Some(ref default) = p.default {
|
||||||
if self_ty.is_none() && default.has_self_ty() {
|
if self_ty.is_none() && default.has_self_ty() {
|
||||||
// There is no suitable inference default for a type parameter
|
// There is no suitable inference default for a type parameter
|
||||||
// that references self with no self-type provided.
|
// that references self with no self-type provided.
|
||||||
return None;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(p.clone())
|
true
|
||||||
}
|
};
|
||||||
|
|
||||||
if param_mode == PathParamMode::Optional && types_provided.is_empty() {
|
if param_mode == PathParamMode::Optional && types_provided.is_empty() {
|
||||||
ty_param_defs
|
ty_param_defs.iter().map(|def| {
|
||||||
.iter()
|
let ty_var = if use_default(def) {
|
||||||
.map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
|
self.ty_infer_for_def(def, &substs, span)
|
||||||
Some(TypeSpace), span))
|
} else {
|
||||||
.collect()
|
self.ty_infer(span)
|
||||||
|
};
|
||||||
|
substs.types.push(def.space, ty_var);
|
||||||
|
ty_var
|
||||||
|
}).collect()
|
||||||
} else {
|
} else {
|
||||||
types_provided
|
types_provided
|
||||||
}
|
}
|
||||||
|
@ -1828,7 +1834,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
// values in a ExprClosure, or as
|
// values in a ExprClosure, or as
|
||||||
// the type of local variables. Both of these cases are
|
// the type of local variables. Both of these cases are
|
||||||
// handled specially and will not descend into this routine.
|
// handled specially and will not descend into this routine.
|
||||||
self.ty_infer(None, None, None, ast_ty.span)
|
self.ty_infer(ast_ty.span)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1845,7 +1851,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
{
|
{
|
||||||
match a.ty.node {
|
match a.ty.node {
|
||||||
hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
|
hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
|
||||||
hir::TyInfer => self.ty_infer(None, None, None, a.ty.span),
|
hir::TyInfer => self.ty_infer(a.ty.span),
|
||||||
_ => self.ast_ty_to_ty(rscope, &a.ty),
|
_ => self.ast_ty_to_ty(rscope, &a.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2067,8 +2073,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
let output_ty = match decl.output {
|
let output_ty = match decl.output {
|
||||||
_ if is_infer && expected_ret_ty.is_some() =>
|
_ if is_infer && expected_ret_ty.is_some() =>
|
||||||
expected_ret_ty.unwrap(),
|
expected_ret_ty.unwrap(),
|
||||||
_ if is_infer =>
|
_ if is_infer => self.ty_infer(decl.output.span()),
|
||||||
self.ty_infer(None, None, None, decl.output.span()),
|
|
||||||
hir::Return(ref output) =>
|
hir::Return(ref output) =>
|
||||||
self.ast_ty_to_ty(&rb, &output),
|
self.ast_ty_to_ty(&rb, &output),
|
||||||
hir::DefaultReturn(..) => bug!(),
|
hir::DefaultReturn(..) => bug!(),
|
||||||
|
|
|
@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn fresh_receiver_substs(&mut self,
|
fn fresh_receiver_substs(&mut self,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
pick: &probe::Pick<'tcx>)
|
pick: &probe::Pick<'tcx>)
|
||||||
-> subst::Substs<'tcx>
|
-> &'tcx subst::Substs<'tcx>
|
||||||
{
|
{
|
||||||
match pick.kind {
|
match pick.kind {
|
||||||
probe::InherentImplPick => {
|
probe::InherentImplPick => {
|
||||||
|
@ -231,7 +231,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
original_poly_trait_ref,
|
original_poly_trait_ref,
|
||||||
upcast_trait_ref,
|
upcast_trait_ref,
|
||||||
trait_def_id);
|
trait_def_id);
|
||||||
upcast_trait_ref.substs.clone()
|
upcast_trait_ref.substs
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,9 +249,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
let impl_trait_ref =
|
let impl_trait_ref =
|
||||||
self.instantiate_type_scheme(
|
self.instantiate_type_scheme(
|
||||||
self.span,
|
self.span,
|
||||||
&impl_polytype.substs,
|
impl_polytype.substs,
|
||||||
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
||||||
impl_trait_ref.substs.clone()
|
impl_trait_ref.substs
|
||||||
}
|
}
|
||||||
|
|
||||||
probe::TraitPick => {
|
probe::TraitPick => {
|
||||||
|
@ -271,7 +271,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
probe::WhereClausePick(ref poly_trait_ref) => {
|
probe::WhereClausePick(ref poly_trait_ref) => {
|
||||||
// Where clauses can have bound regions in them. We need to instantiate
|
// Where clauses can have bound regions in them. We need to instantiate
|
||||||
// those to convert from a poly-trait-ref to a trait-ref.
|
// those to convert from a poly-trait-ref to a trait-ref.
|
||||||
self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs.clone()
|
self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,8 +303,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn instantiate_method_substs(&mut self,
|
fn instantiate_method_substs(&mut self,
|
||||||
pick: &probe::Pick<'tcx>,
|
pick: &probe::Pick<'tcx>,
|
||||||
supplied_method_types: Vec<Ty<'tcx>>,
|
mut supplied_method_types: Vec<Ty<'tcx>>,
|
||||||
substs: subst::Substs<'tcx>)
|
substs: &subst::Substs<'tcx>)
|
||||||
-> subst::Substs<'tcx>
|
-> subst::Substs<'tcx>
|
||||||
{
|
{
|
||||||
// Determine the values for the generic parameters of the method.
|
// Determine the values for the generic parameters of the method.
|
||||||
|
@ -312,50 +312,42 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// variables.
|
// variables.
|
||||||
let num_supplied_types = supplied_method_types.len();
|
let num_supplied_types = supplied_method_types.len();
|
||||||
let method = pick.item.as_opt_method().unwrap();
|
let method = pick.item.as_opt_method().unwrap();
|
||||||
let method_types = method.generics.types.get_slice(subst::FnSpace);
|
let num_method_types = method.generics.types.len(subst::FnSpace);
|
||||||
let num_method_types = method_types.len();
|
|
||||||
|
|
||||||
|
if num_supplied_types > 0 && num_supplied_types != num_method_types {
|
||||||
|
if num_method_types == 0 {
|
||||||
|
span_err!(self.tcx.sess, self.span, E0035,
|
||||||
|
"does not take type parameters");
|
||||||
|
} else {
|
||||||
|
span_err!(self.tcx.sess, self.span, E0036,
|
||||||
|
"incorrect number of type parameters given for this method: \
|
||||||
|
expected {}, found {}",
|
||||||
|
num_method_types, num_supplied_types);
|
||||||
|
}
|
||||||
|
supplied_method_types = vec![self.tcx.types.err; num_method_types];
|
||||||
|
}
|
||||||
|
|
||||||
// Create subst for early-bound lifetime parameters, combining
|
// Create subst for early-bound lifetime parameters, combining
|
||||||
// parameters from the type and those from the method.
|
// parameters from the type and those from the method.
|
||||||
//
|
//
|
||||||
// FIXME -- permit users to manually specify lifetimes
|
// FIXME -- permit users to manually specify lifetimes
|
||||||
let method_regions =
|
let type_defs = method.generics.types.as_full_slice();
|
||||||
self.region_vars_for_defs(
|
let region_defs = method.generics.regions.as_full_slice();
|
||||||
self.span,
|
subst::Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||||
pick.item.as_opt_method().unwrap()
|
if def.space != subst::FnSpace {
|
||||||
.generics.regions.get_slice(subst::FnSpace));
|
substs.region_for_def(def)
|
||||||
|
} else {
|
||||||
let subst::Substs { types, regions } = substs;
|
self.region_var_for_def(self.span, def)
|
||||||
let regions = regions.with_slice(subst::FnSpace, &method_regions);
|
}
|
||||||
let mut final_substs = subst::Substs { types: types, regions: regions };
|
}, |def, cur_substs| {
|
||||||
|
if def.space != subst::FnSpace {
|
||||||
if num_supplied_types == 0 {
|
substs.type_for_def(def)
|
||||||
self.type_vars_for_defs(
|
} else if supplied_method_types.is_empty() {
|
||||||
self.span,
|
self.type_var_for_def(self.span, def, cur_substs)
|
||||||
subst::FnSpace,
|
} else {
|
||||||
&mut final_substs,
|
supplied_method_types[def.index as usize]
|
||||||
method_types);
|
}
|
||||||
} else if num_method_types == 0 {
|
})
|
||||||
span_err!(self.tcx.sess, self.span, E0035,
|
|
||||||
"does not take type parameters");
|
|
||||||
self.type_vars_for_defs(
|
|
||||||
self.span,
|
|
||||||
subst::FnSpace,
|
|
||||||
&mut final_substs,
|
|
||||||
method_types);
|
|
||||||
} else if num_supplied_types != num_method_types {
|
|
||||||
span_err!(self.tcx.sess, self.span, E0036,
|
|
||||||
"incorrect number of type parameters given for this method: expected {}, found {}",
|
|
||||||
num_method_types, num_supplied_types);
|
|
||||||
final_substs.types.replace(
|
|
||||||
subst::FnSpace,
|
|
||||||
vec![self.tcx.types.err; num_method_types]);
|
|
||||||
} else {
|
|
||||||
final_substs.types.replace(subst::FnSpace, supplied_method_types);
|
|
||||||
}
|
|
||||||
|
|
||||||
return final_substs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify_receivers(&mut self,
|
fn unify_receivers(&mut self,
|
||||||
|
|
|
@ -182,29 +182,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
||||||
|
|
||||||
let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
|
if let Some(ref input_types) = opt_input_types {
|
||||||
let expected_number_of_input_types = type_parameter_defs.len();
|
assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len());
|
||||||
|
}
|
||||||
assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
|
assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
|
||||||
assert!(trait_def.generics.regions.is_empty());
|
assert!(trait_def.generics.regions.is_empty());
|
||||||
|
|
||||||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||||
let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty);
|
let type_defs = trait_def.generics.types.as_full_slice();
|
||||||
|
let region_defs = trait_def.generics.regions.as_full_slice();
|
||||||
match opt_input_types {
|
let substs = subst::Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||||
Some(input_types) => {
|
self.region_var_for_def(span, def)
|
||||||
assert_eq!(expected_number_of_input_types, input_types.len());
|
}, |def, substs| {
|
||||||
substs.types.replace(subst::ParamSpace::TypeSpace, input_types);
|
if def.space == subst::SelfSpace {
|
||||||
|
self_ty
|
||||||
|
} else if let Some(ref input_types) = opt_input_types {
|
||||||
|
input_types[def.index as usize]
|
||||||
|
} else {
|
||||||
|
self.type_var_for_def(span, def, substs)
|
||||||
}
|
}
|
||||||
|
});
|
||||||
None => {
|
|
||||||
self.type_vars_for_defs(
|
|
||||||
span,
|
|
||||||
subst::ParamSpace::TypeSpace,
|
|
||||||
&mut substs,
|
|
||||||
type_parameter_defs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs));
|
let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs));
|
||||||
|
|
||||||
|
|
|
@ -1227,28 +1227,29 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
return impl_ty;
|
return impl_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut placeholder;
|
let placeholder;
|
||||||
let mut substs = substs;
|
let mut substs = substs;
|
||||||
if
|
if
|
||||||
!method.generics.types.is_empty_in(subst::FnSpace) ||
|
!method.generics.types.is_empty_in(subst::FnSpace) ||
|
||||||
!method.generics.regions.is_empty_in(subst::FnSpace)
|
!method.generics.regions.is_empty_in(subst::FnSpace)
|
||||||
{
|
{
|
||||||
// In general, during probe we erase regions. See
|
let type_defs = method.generics.types.as_full_slice();
|
||||||
// `impl_self_ty()` for an explanation.
|
let region_defs = method.generics.regions.as_full_slice();
|
||||||
let method_regions =
|
placeholder = subst::Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||||
method.generics.regions.get_slice(subst::FnSpace)
|
if def.space != subst::FnSpace {
|
||||||
.iter()
|
substs.region_for_def(def)
|
||||||
.map(|_| ty::ReErased)
|
} else {
|
||||||
.collect();
|
// In general, during probe we erase regions. See
|
||||||
|
// `impl_self_ty()` for an explanation.
|
||||||
placeholder = (*substs).clone().with_method(Vec::new(), method_regions);
|
ty::ReErased
|
||||||
|
}
|
||||||
self.type_vars_for_defs(
|
}, |def, cur_substs| {
|
||||||
self.span,
|
if def.space != subst::FnSpace {
|
||||||
subst::FnSpace,
|
substs.type_for_def(def)
|
||||||
&mut placeholder,
|
} else {
|
||||||
method.generics.types.get_slice(subst::FnSpace));
|
self.type_var_for_def(self.span, def, cur_substs)
|
||||||
|
}
|
||||||
|
});
|
||||||
substs = &placeholder;
|
substs = &placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1358,27 +1358,15 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
trait_def.associated_type_names.contains(&assoc_name)
|
trait_def.associated_type_names.contains(&assoc_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_infer(&self,
|
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
|
||||||
ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
|
self.next_ty_var()
|
||||||
substs: Option<&mut subst::Substs<'tcx>>,
|
}
|
||||||
space: Option<subst::ParamSpace>,
|
|
||||||
span: Span) -> Ty<'tcx> {
|
|
||||||
// Grab the default doing subsitution
|
|
||||||
let default = ty_param_def.and_then(|def| {
|
|
||||||
def.default.map(|ty| type_variable::Default {
|
|
||||||
ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
|
|
||||||
origin_span: span,
|
|
||||||
def_id: def.default_def_id
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
let ty_var = self.next_ty_var_with_default(default);
|
fn ty_infer_for_def(&self,
|
||||||
|
ty_param_def: &ty::TypeParameterDef<'tcx>,
|
||||||
// Finally we add the type variable to the substs
|
substs: &subst::Substs<'tcx>,
|
||||||
match substs {
|
span: Span) -> Ty<'tcx> {
|
||||||
None => ty_var,
|
self.type_var_for_def(span, ty_param_def, substs)
|
||||||
Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn projected_ty_from_poly_trait_ref(&self,
|
fn projected_ty_from_poly_trait_ref(&self,
|
||||||
|
@ -2785,20 +2773,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
span: Span, // (potential) receiver for this impl
|
span: Span, // (potential) receiver for this impl
|
||||||
did: DefId)
|
did: DefId)
|
||||||
-> TypeAndSubsts<'tcx> {
|
-> TypeAndSubsts<'tcx> {
|
||||||
let tcx = self.tcx;
|
let ity = self.tcx.lookup_item_type(did);
|
||||||
|
debug!("impl_self_ty: ity={:?}", ity);
|
||||||
|
|
||||||
let ity = tcx.lookup_item_type(did);
|
let substs = self.fresh_substs_for_generics(span, &ity.generics);
|
||||||
let (tps, rps, raw_ty) =
|
let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty);
|
||||||
(ity.generics.types.get_slice(subst::TypeSpace),
|
|
||||||
ity.generics.regions.get_slice(subst::TypeSpace),
|
|
||||||
ity.ty);
|
|
||||||
|
|
||||||
debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
|
|
||||||
|
|
||||||
let rps = self.region_vars_for_defs(span, rps);
|
|
||||||
let mut substs = subst::Substs::new_type(vec![], rps);
|
|
||||||
self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
|
|
||||||
let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty);
|
|
||||||
|
|
||||||
TypeAndSubsts { substs: substs, ty: substd_ty }
|
TypeAndSubsts { substs: substs, ty: substd_ty }
|
||||||
}
|
}
|
||||||
|
@ -4532,7 +4511,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// everything.
|
// everything.
|
||||||
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
|
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
|
||||||
substs.types.replace(space, Vec::new());
|
substs.types.replace(space, Vec::new());
|
||||||
self.type_vars_for_defs(span, space, substs, &desired[..]);
|
for def in desired {
|
||||||
|
let ty_var = self.type_var_for_def(span, def, substs);
|
||||||
|
substs.types.push(def.space, ty_var);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,11 +362,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_infer(&self,
|
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
|
||||||
_ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
|
|
||||||
_substs: Option<&mut Substs<'tcx>>,
|
|
||||||
_space: Option<ParamSpace>,
|
|
||||||
span: Span) -> Ty<'tcx> {
|
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
self.tcx().sess,
|
self.tcx().sess,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub mod coherence;
|
||||||
pub mod variance;
|
pub mod variance;
|
||||||
|
|
||||||
pub struct TypeAndSubsts<'tcx> {
|
pub struct TypeAndSubsts<'tcx> {
|
||||||
pub substs: Substs<'tcx>,
|
pub substs: &'tcx Substs<'tcx>,
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -464,7 +464,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
self.declared_variance(p.def_id, def_id, TypeParam,
|
self.declared_variance(p.def_id, def_id, TypeParam,
|
||||||
p.space, p.index as usize);
|
p.space, p.index as usize);
|
||||||
let variance_i = self.xform(variance, variance_decl);
|
let variance_i = self.xform(variance, variance_decl);
|
||||||
let substs_ty = *substs.types.get(p.space, p.index as usize);
|
let substs_ty = substs.type_for_def(p);
|
||||||
debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
|
debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
|
||||||
variance_decl, variance_i);
|
variance_decl, variance_i);
|
||||||
self.add_constraints_from_ty(generics, substs_ty, variance_i);
|
self.add_constraints_from_ty(generics, substs_ty, variance_i);
|
||||||
|
@ -475,7 +475,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
self.declared_variance(p.def_id, def_id,
|
self.declared_variance(p.def_id, def_id,
|
||||||
RegionParam, p.space, p.index as usize);
|
RegionParam, p.space, p.index as usize);
|
||||||
let variance_i = self.xform(variance, variance_decl);
|
let variance_i = self.xform(variance, variance_decl);
|
||||||
let substs_r = *substs.regions.get(p.space, p.index as usize);
|
let substs_r = substs.region_for_def(p);
|
||||||
self.add_constraints_from_region(generics, substs_r, variance_i);
|
self.add_constraints_from_region(generics, substs_r, variance_i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue