diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index eaa5b6d58f8..253f6379d15 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -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 { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 4e98ef27531..7d8a20c42e3 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -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 { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 488428833ac..12e14dbcb92 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -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, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 767797e843c..1bcb7a5ce03 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -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 diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b190e7a7a48..44d769a799f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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; } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 42b28dcbc1b..fd99d1ddba9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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; }