1
Fork 0

rustc: move defaulting's use of &mut Substs from InferCtxt to typeck.

This commit is contained in:
Eduard Burtescu 2016-08-17 03:56:18 +03:00
parent c87063f07e
commit 5ef6af09e3
12 changed files with 212 additions and 231 deletions

View file

@ -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 {

View file

@ -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();

View file

@ -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)
} }

View file

@ -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()
} }

View file

@ -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!(),

View file

@ -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,

View file

@ -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));

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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,

View file

@ -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>,
} }

View file

@ -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);
} }
} }