mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
rustc: move defaulting's use of &mut Substs from InferCtxt to typeck.
This commit is contained in:
parent
c87063f07e
commit
5ef6af09e3
@ -1172,15 +1172,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
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> {
|
||||
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))
|
||||
}
|
||||
|
||||
/// 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,
|
||||
span: Span,
|
||||
defs: &[ty::RegionParameterDef])
|
||||
-> Vec<ty::Region> {
|
||||
defs.iter()
|
||||
.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);
|
||||
}
|
||||
defs.iter().map(|def| self.region_var_for_def(span, def)).collect()
|
||||
}
|
||||
|
||||
/// 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>)
|
||||
-> &'tcx subst::Substs<'tcx>
|
||||
{
|
||||
let type_params = subst::VecPerParamSpace::empty();
|
||||
|
||||
let region_params =
|
||||
generics.regions.map(
|
||||
|d| self.next_region_var(EarlyBoundRegion(span, d.name)));
|
||||
|
||||
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));
|
||||
}
|
||||
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| {
|
||||
self.type_var_for_def(span, def, substs)
|
||||
});
|
||||
|
||||
self.tcx.mk_substs(substs)
|
||||
}
|
||||
@ -1269,25 +1266,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
self_ty: Ty<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
-> &'tcx subst::Substs<'tcx>
|
||||
{
|
||||
|
||||
assert!(generics.types.len(subst::SelfSpace) == 1);
|
||||
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);
|
||||
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;
|
||||
self.tcx.mk_substs(substs)
|
||||
}
|
||||
|
||||
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::fast_reject;
|
||||
use ty::fold::TypeFolder;
|
||||
use ty::subst::{self, Subst, TypeSpace};
|
||||
use ty::subst::{Subst, TypeSpace};
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
|
||||
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 {
|
||||
/// returns the fuzzy category of a given type, or None
|
||||
/// 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)
|
||||
.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
|
||||
.impl_trait_ref(def_id)
|
||||
.unwrap()
|
||||
.subst(tcx, &self.impl_substs(def_id, obligation.clone()));
|
||||
.subst(tcx, impl_substs);
|
||||
|
||||
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)
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
let tcx = infcx.tcx;
|
||||
let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
|
||||
let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).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 {
|
||||
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)
|
||||
}
|
||||
|
||||
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>> {
|
||||
self.types.get_self().cloned()
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ use hir::def_id::DefId;
|
||||
use hir::print as pprust;
|
||||
use middle::resolve_lifetime as rl;
|
||||
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::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||
use rustc::ty::wf::object_region_bounds;
|
||||
@ -115,11 +115,15 @@ pub trait AstConv<'gcx, 'tcx> {
|
||||
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
|
||||
|
||||
/// What type should we use when a type is omitted?
|
||||
fn ty_infer(&self,
|
||||
param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
|
||||
substs: Option<&mut Substs<'tcx>>,
|
||||
space: Option<ParamSpace>,
|
||||
span: Span) -> Ty<'tcx>;
|
||||
fn ty_infer(&self, span: Span) -> Ty<'tcx>;
|
||||
|
||||
/// Same as ty_infer, but with a known type parameter definition.
|
||||
fn ty_infer_for_def(&self,
|
||||
_def: &ty::TypeParameterDef<'tcx>,
|
||||
_substs: &Substs<'tcx>,
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.ty_infer(span)
|
||||
}
|
||||
|
||||
/// Projecting an associated type from a (potentially)
|
||||
/// 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>>)
|
||||
-> Vec<Ty<'tcx>>
|
||||
{
|
||||
fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
|
||||
-> Option<ty::TypeParameterDef<'tcx>>
|
||||
{
|
||||
let use_default = |p: &ty::TypeParameterDef<'tcx>| {
|
||||
if let Some(ref default) = p.default {
|
||||
if self_ty.is_none() && default.has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// 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() {
|
||||
ty_param_defs
|
||||
.iter()
|
||||
.map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
|
||||
Some(TypeSpace), span))
|
||||
.collect()
|
||||
ty_param_defs.iter().map(|def| {
|
||||
let ty_var = if use_default(def) {
|
||||
self.ty_infer_for_def(def, &substs, span)
|
||||
} else {
|
||||
self.ty_infer(span)
|
||||
};
|
||||
substs.types.push(def.space, ty_var);
|
||||
ty_var
|
||||
}).collect()
|
||||
} else {
|
||||
types_provided
|
||||
}
|
||||
@ -1828,7 +1834,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
// values in a ExprClosure, or as
|
||||
// the type of local variables. Both of these cases are
|
||||
// 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 {
|
||||
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),
|
||||
}
|
||||
}
|
||||
@ -2067,8 +2073,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
let output_ty = match decl.output {
|
||||
_ if is_infer && expected_ret_ty.is_some() =>
|
||||
expected_ret_ty.unwrap(),
|
||||
_ if is_infer =>
|
||||
self.ty_infer(None, None, None, decl.output.span()),
|
||||
_ if is_infer => self.ty_infer(decl.output.span()),
|
||||
hir::Return(ref output) =>
|
||||
self.ast_ty_to_ty(&rb, &output),
|
||||
hir::DefaultReturn(..) => bug!(),
|
||||
|
@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
fn fresh_receiver_substs(&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
pick: &probe::Pick<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
-> &'tcx subst::Substs<'tcx>
|
||||
{
|
||||
match pick.kind {
|
||||
probe::InherentImplPick => {
|
||||
@ -231,7 +231,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
original_poly_trait_ref,
|
||||
upcast_trait_ref,
|
||||
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 =
|
||||
self.instantiate_type_scheme(
|
||||
self.span,
|
||||
&impl_polytype.substs,
|
||||
impl_polytype.substs,
|
||||
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
||||
impl_trait_ref.substs.clone()
|
||||
impl_trait_ref.substs
|
||||
}
|
||||
|
||||
probe::TraitPick => {
|
||||
@ -271,7 +271,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
probe::WhereClausePick(ref poly_trait_ref) => {
|
||||
// Where clauses can have bound regions in them. We need to instantiate
|
||||
// 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,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
supplied_method_types: Vec<Ty<'tcx>>,
|
||||
substs: subst::Substs<'tcx>)
|
||||
mut supplied_method_types: Vec<Ty<'tcx>>,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
// Determine the values for the generic parameters of the method.
|
||||
@ -312,50 +312,42 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
// variables.
|
||||
let num_supplied_types = supplied_method_types.len();
|
||||
let method = pick.item.as_opt_method().unwrap();
|
||||
let method_types = method.generics.types.get_slice(subst::FnSpace);
|
||||
let num_method_types = method_types.len();
|
||||
let num_method_types = method.generics.types.len(subst::FnSpace);
|
||||
|
||||
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
|
||||
// parameters from the type and those from the method.
|
||||
//
|
||||
// FIXME -- permit users to manually specify lifetimes
|
||||
let method_regions =
|
||||
self.region_vars_for_defs(
|
||||
self.span,
|
||||
pick.item.as_opt_method().unwrap()
|
||||
.generics.regions.get_slice(subst::FnSpace));
|
||||
|
||||
let subst::Substs { types, regions } = substs;
|
||||
let regions = regions.with_slice(subst::FnSpace, &method_regions);
|
||||
let mut final_substs = subst::Substs { types: types, regions: regions };
|
||||
|
||||
if num_supplied_types == 0 {
|
||||
self.type_vars_for_defs(
|
||||
self.span,
|
||||
subst::FnSpace,
|
||||
&mut final_substs,
|
||||
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;
|
||||
let type_defs = method.generics.types.as_full_slice();
|
||||
let region_defs = method.generics.regions.as_full_slice();
|
||||
subst::Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||
if def.space != subst::FnSpace {
|
||||
substs.region_for_def(def)
|
||||
} else {
|
||||
self.region_var_for_def(self.span, def)
|
||||
}
|
||||
}, |def, cur_substs| {
|
||||
if def.space != subst::FnSpace {
|
||||
substs.type_for_def(def)
|
||||
} else if supplied_method_types.is_empty() {
|
||||
self.type_var_for_def(self.span, def, cur_substs)
|
||||
} else {
|
||||
supplied_method_types[def.index as usize]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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 type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
|
||||
let expected_number_of_input_types = type_parameter_defs.len();
|
||||
|
||||
if let Some(ref input_types) = opt_input_types {
|
||||
assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len());
|
||||
}
|
||||
assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
|
||||
assert!(trait_def.generics.regions.is_empty());
|
||||
|
||||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||
let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty);
|
||||
|
||||
match opt_input_types {
|
||||
Some(input_types) => {
|
||||
assert_eq!(expected_number_of_input_types, input_types.len());
|
||||
substs.types.replace(subst::ParamSpace::TypeSpace, input_types);
|
||||
let type_defs = trait_def.generics.types.as_full_slice();
|
||||
let region_defs = trait_def.generics.regions.as_full_slice();
|
||||
let substs = subst::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 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));
|
||||
|
||||
|
@ -1227,28 +1227,29 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
return impl_ty;
|
||||
}
|
||||
|
||||
let mut placeholder;
|
||||
let placeholder;
|
||||
let mut substs = substs;
|
||||
if
|
||||
!method.generics.types.is_empty_in(subst::FnSpace) ||
|
||||
!method.generics.regions.is_empty_in(subst::FnSpace)
|
||||
{
|
||||
// In general, during probe we erase regions. See
|
||||
// `impl_self_ty()` for an explanation.
|
||||
let method_regions =
|
||||
method.generics.regions.get_slice(subst::FnSpace)
|
||||
.iter()
|
||||
.map(|_| ty::ReErased)
|
||||
.collect();
|
||||
|
||||
placeholder = (*substs).clone().with_method(Vec::new(), method_regions);
|
||||
|
||||
self.type_vars_for_defs(
|
||||
self.span,
|
||||
subst::FnSpace,
|
||||
&mut placeholder,
|
||||
method.generics.types.get_slice(subst::FnSpace));
|
||||
|
||||
let type_defs = method.generics.types.as_full_slice();
|
||||
let region_defs = method.generics.regions.as_full_slice();
|
||||
placeholder = subst::Substs::from_param_defs(region_defs, type_defs, |def| {
|
||||
if def.space != subst::FnSpace {
|
||||
substs.region_for_def(def)
|
||||
} else {
|
||||
// In general, during probe we erase regions. See
|
||||
// `impl_self_ty()` for an explanation.
|
||||
ty::ReErased
|
||||
}
|
||||
}, |def, cur_substs| {
|
||||
if def.space != subst::FnSpace {
|
||||
substs.type_for_def(def)
|
||||
} else {
|
||||
self.type_var_for_def(self.span, def, cur_substs)
|
||||
}
|
||||
});
|
||||
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)
|
||||
}
|
||||
|
||||
fn ty_infer(&self,
|
||||
ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
|
||||
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
|
||||
})
|
||||
});
|
||||
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
|
||||
self.next_ty_var()
|
||||
}
|
||||
|
||||
let ty_var = self.next_ty_var_with_default(default);
|
||||
|
||||
// Finally we add the type variable to the substs
|
||||
match substs {
|
||||
None => ty_var,
|
||||
Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
|
||||
}
|
||||
fn ty_infer_for_def(&self,
|
||||
ty_param_def: &ty::TypeParameterDef<'tcx>,
|
||||
substs: &subst::Substs<'tcx>,
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.type_var_for_def(span, ty_param_def, substs)
|
||||
}
|
||||
|
||||
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
|
||||
did: DefId)
|
||||
-> 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 (tps, rps, raw_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);
|
||||
let substs = self.fresh_substs_for_generics(span, &ity.generics);
|
||||
let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty);
|
||||
|
||||
TypeAndSubsts { substs: substs, ty: substd_ty }
|
||||
}
|
||||
@ -4532,7 +4511,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// everything.
|
||||
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -362,11 +362,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
||||
None
|
||||
}
|
||||
|
||||
fn ty_infer(&self,
|
||||
_ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
|
||||
_substs: Option<&mut Substs<'tcx>>,
|
||||
_space: Option<ParamSpace>,
|
||||
span: Span) -> Ty<'tcx> {
|
||||
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
|
||||
struct_span_err!(
|
||||
self.tcx().sess,
|
||||
span,
|
||||
|
@ -132,7 +132,7 @@ pub mod coherence;
|
||||
pub mod variance;
|
||||
|
||||
pub struct TypeAndSubsts<'tcx> {
|
||||
pub substs: Substs<'tcx>,
|
||||
pub substs: &'tcx Substs<'tcx>,
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
self.declared_variance(p.def_id, def_id, TypeParam,
|
||||
p.space, p.index as usize);
|
||||
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={:?}",
|
||||
variance_decl, 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,
|
||||
RegionParam, p.space, p.index as usize);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user