From 5ef6af09e3b9df3dd01f0e4d53176b0a72ce5722 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 17 Aug 2016 03:56:18 +0300 Subject: [PATCH] rustc: move defaulting's use of &mut Substs from InferCtxt to typeck. --- src/librustc/infer/mod.rs | 122 ++++++++++---------- src/librustc/traits/error_reporting.rs | 28 +---- src/librustc/traits/util.rs | 3 +- src/librustc/ty/subst.rs | 31 +++++ src/librustc_typeck/astconv.rs | 47 ++++---- src/librustc_typeck/check/method/confirm.rs | 82 ++++++------- src/librustc_typeck/check/method/mod.rs | 33 +++--- src/librustc_typeck/check/method/probe.rs | 35 +++--- src/librustc_typeck/check/mod.rs | 50 +++----- src/librustc_typeck/collect.rs | 6 +- src/librustc_typeck/lib.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 4 +- 12 files changed, 212 insertions(+), 231 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 24fadc549fa..79eea7314cd 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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>) -> 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(...);` when + /// used in a path such as `Foo::::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 { - 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 { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b5133738ada..5d50eac1716 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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(); diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 818eb4eb2fb..80a3ad9122b 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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) } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 63399ee1388..34e7899e2fd 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -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(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> { self.types.get_self().cloned() } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a0af98dec72..ea7b447632c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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>, - substs: Option<&mut Substs<'tcx>>, - space: Option, - 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>) -> Vec> { - fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option>) - -> Option> - { + 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!(), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5fac65bbfd6..d1d72599555 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -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>, - substs: subst::Substs<'tcx>) + mut supplied_method_types: Vec>, + 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, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e6401be5b3e..532a5c0de4e 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -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` - 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)); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index e4701bb1195..44e371482c5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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; } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fae64f37419..b5018d51b7f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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>, - substs: Option<&mut subst::Substs<'tcx>>, - space: Option, - 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; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 69545aefb44..0ddc051d4a8 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -362,11 +362,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { None } - fn ty_infer(&self, - _ty_param_def: Option>, - _substs: Option<&mut Substs<'tcx>>, - _space: Option, - span: Span) -> Ty<'tcx> { + fn ty_infer(&self, span: Span) -> Ty<'tcx> { struct_span_err!( self.tcx().sess, span, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 11743ade2d4..4ce6f8210c3 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -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>, } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 1e342d4b819..50c568cfef8 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -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); } }