mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-10 02:56:52 +00:00
Correctly subst defaults with the in-scope substs
This commit is contained in:
parent
b75f215e82
commit
fbfbdd7d14
@ -1047,12 +1047,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
.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,
|
||||
// substs: Substs,
|
||||
defs: &[ty::TypeParameterDef<'tcx>])
|
||||
-> Vec<ty::Ty<'tcx>> {
|
||||
space: subst::ParamSpace,
|
||||
substs: &mut Substs<'tcx>,
|
||||
defs: &[ty::TypeParameterDef<'tcx>]) {
|
||||
|
||||
// This doesn't work ...
|
||||
fn definition_span<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: ast::DefId) -> Span {
|
||||
let parent = tcx.map.get_parent(def_id.node);
|
||||
debug!("definition_span def_id={:?} parent={:?} node={:?} parent_node={:?}",
|
||||
@ -1069,24 +1072,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut substs = Substs::empty();
|
||||
let mut vars = Vec::with_capacity(defs.len());
|
||||
|
||||
for def in defs.iter() {
|
||||
let default = def.default.map(|default| {
|
||||
let default = def.default.subst_spanned(self.tcx, substs, Some(span)).map(|default| {
|
||||
type_variable::Default {
|
||||
ty: default,
|
||||
origin_span: span,
|
||||
definition_span: definition_span(self.tcx, def.def_id)
|
||||
}
|
||||
});
|
||||
//.subst(self.tcx, &substs)
|
||||
|
||||
let ty_var = self.next_ty_var_with_default(default);
|
||||
substs.types.push(subst::ParamSpace::SelfSpace, ty_var);
|
||||
substs.types.push(space, ty_var);
|
||||
vars.push(ty_var)
|
||||
}
|
||||
|
||||
vars
|
||||
}
|
||||
|
||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
||||
@ -1096,17 +1096,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
generics: &ty::Generics<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
let mut type_params = subst::VecPerParamSpace::empty();
|
||||
|
||||
for space in subst::ParamSpace::all().iter() {
|
||||
type_params.replace(*space,
|
||||
self.type_vars_for_defs(span, generics.types.get_slice(*space)))
|
||||
}
|
||||
let type_params = subst::VecPerParamSpace::empty();
|
||||
|
||||
let region_params =
|
||||
generics.regions.map(
|
||||
|d| self.next_region_var(EarlyBoundRegion(span, d.name)));
|
||||
subst::Substs::new(type_params, region_params)
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
return substs;
|
||||
}
|
||||
|
||||
/// Given a set of generics defined on a trait, returns a substitution mapping each output
|
||||
@ -1124,13 +1130,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
assert!(generics.regions.len(subst::SelfSpace) == 0);
|
||||
assert!(generics.regions.len(subst::FnSpace) == 0);
|
||||
|
||||
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
|
||||
let type_parameters = self.type_vars_for_defs(span, type_parameter_defs);
|
||||
let type_params = Vec::new();
|
||||
|
||||
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
|
||||
let regions = self.region_vars_for_defs(span, region_param_defs);
|
||||
|
||||
subst::Substs::new_trait(type_parameters, regions, self_ty)
|
||||
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 {
|
||||
|
@ -154,7 +154,7 @@ impl<'tcx> Substs<'tcx> {
|
||||
}
|
||||
|
||||
impl RegionSubsts {
|
||||
fn map<F>(self, op: F) -> RegionSubsts where
|
||||
pub fn map<F>(self, op: F) -> RegionSubsts where
|
||||
F: FnOnce(VecPerParamSpace<ty::Region>) -> VecPerParamSpace<ty::Region>,
|
||||
{
|
||||
match self {
|
||||
|
@ -84,9 +84,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
|
||||
// Create substitutions for the method's type parameters.
|
||||
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
||||
let (method_types, method_regions) =
|
||||
self.instantiate_method_substs(&pick, supplied_method_types);
|
||||
let all_substs = rcvr_substs.with_method(method_types, method_regions);
|
||||
let all_substs =
|
||||
self.instantiate_method_substs(
|
||||
&pick,
|
||||
supplied_method_types,
|
||||
rcvr_substs);
|
||||
|
||||
debug!("all_substs={:?}", all_substs);
|
||||
|
||||
// Create the final signature for the method, replacing late-bound regions.
|
||||
@ -302,8 +305,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
|
||||
fn instantiate_method_substs(&mut self,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
supplied_method_types: Vec<Ty<'tcx>>)
|
||||
-> (Vec<Ty<'tcx>>, Vec<ty::Region>)
|
||||
supplied_method_types: Vec<Ty<'tcx>>,
|
||||
substs: subst::Substs<'tcx>)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
// Determine the values for the generic parameters of the method.
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
@ -313,21 +317,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
let method_types = method.generics.types.get_slice(subst::FnSpace);
|
||||
let num_method_types = method_types.len();
|
||||
|
||||
let method_types = {
|
||||
if num_supplied_types == 0 {
|
||||
self.fcx.infcx().type_vars_for_defs(self.span, method_types)
|
||||
} else if num_method_types == 0 {
|
||||
span_err!(self.tcx().sess, self.span, E0035,
|
||||
"does not take type parameters");
|
||||
self.fcx.infcx().type_vars_for_defs(self.span, 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");
|
||||
vec![self.tcx().types.err; num_method_types]
|
||||
} else {
|
||||
supplied_method_types
|
||||
}
|
||||
};
|
||||
|
||||
// Create subst for early-bound lifetime parameters, combining
|
||||
// parameters from the type and those from the method.
|
||||
@ -339,7 +328,33 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
pick.item.as_opt_method().unwrap()
|
||||
.generics.regions.get_slice(subst::FnSpace));
|
||||
|
||||
(method_types, method_regions)
|
||||
let subst::Substs { types, regions } = substs;
|
||||
let regions = regions.map(|r| r.with_vec(subst::FnSpace, method_regions));
|
||||
let mut final_substs = subst::Substs { types: types, regions: regions };
|
||||
|
||||
if num_supplied_types == 0 {
|
||||
self.fcx.infcx().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.fcx.infcx().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");
|
||||
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,
|
||||
|
@ -169,22 +169,28 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
|
||||
let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
|
||||
let expected_number_of_input_types = type_parameter_defs.len();
|
||||
let input_types = match opt_input_types {
|
||||
Some(input_types) => {
|
||||
assert_eq!(expected_number_of_input_types, input_types.len());
|
||||
input_types
|
||||
}
|
||||
|
||||
None => {
|
||||
fcx.inh.infcx.type_vars_for_defs(span, type_parameter_defs)
|
||||
}
|
||||
};
|
||||
|
||||
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 substs = subst::Substs::new_trait(input_types, Vec::new(), self_ty);
|
||||
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);
|
||||
}
|
||||
|
||||
None => {
|
||||
fcx.inh.infcx.type_vars_for_defs(
|
||||
span,
|
||||
subst::ParamSpace::TypeSpace,
|
||||
&mut substs,
|
||||
type_parameter_defs);
|
||||
}
|
||||
}
|
||||
|
||||
let trait_ref = ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs));
|
||||
|
||||
// Construct an obligation
|
||||
|
@ -1200,16 +1200,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
return impl_ty;
|
||||
}
|
||||
|
||||
let placeholder;
|
||||
let mut placeholder;
|
||||
let mut substs = substs;
|
||||
if
|
||||
!method.generics.types.is_empty_in(subst::FnSpace) ||
|
||||
!method.generics.regions.is_empty_in(subst::FnSpace)
|
||||
{
|
||||
let method_types =
|
||||
self.infcx().type_vars_for_defs(self.span,
|
||||
method.generics.types.get_slice(subst::FnSpace));
|
||||
|
||||
// In general, during probe we erase regions. See
|
||||
// `impl_self_ty()` for an explanation.
|
||||
let method_regions =
|
||||
@ -1218,7 +1214,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
.map(|_| ty::ReStatic)
|
||||
.collect();
|
||||
|
||||
placeholder = (*substs).clone().with_method(method_types, method_regions);
|
||||
placeholder = (*substs).clone().with_method(Vec::new(), method_regions);
|
||||
|
||||
self.infcx().type_vars_for_defs(
|
||||
self.span,
|
||||
subst::FnSpace,
|
||||
&mut placeholder,
|
||||
method.generics.types.get_slice(subst::FnSpace));
|
||||
|
||||
substs = &placeholder;
|
||||
}
|
||||
|
||||
|
@ -2616,8 +2616,10 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
|
||||
|
||||
let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
|
||||
let tps = fcx.inh.infcx.type_vars_for_defs(span, tps);
|
||||
let substs = subst::Substs::new_type(tps, rps);
|
||||
let mut substs = subst::Substs::new(
|
||||
VecPerParamSpace::empty(),
|
||||
VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
|
||||
fcx.inh.infcx.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
|
||||
let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
|
||||
|
||||
TypeAndSubsts { substs: substs, ty: substd_ty }
|
||||
@ -4611,6 +4613,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(self_ty) = opt_self_ty {
|
||||
if type_defs.len(subst::SelfSpace) == 1 {
|
||||
substs.types.push(subst::SelfSpace, self_ty);
|
||||
@ -4623,7 +4626,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// variables. If the user provided some types, we may still need
|
||||
// to add defaults. If the user provided *too many* types, that's
|
||||
// a problem.
|
||||
for &space in &ParamSpace::all() {
|
||||
for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
|
||||
adjust_type_parameters(fcx, span, space, type_defs,
|
||||
require_type_space, &mut substs);
|
||||
assert_eq!(substs.types.len(space), type_defs.len(space));
|
||||
@ -4836,7 +4839,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// Nothing specified at all: supply inference variables for
|
||||
// everything.
|
||||
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
|
||||
substs.types.replace(space, fcx.infcx().type_vars_for_defs(span, &desired[..]));
|
||||
fcx.infcx().type_vars_for_defs(span, space, substs, &desired[..]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user