diff options
| author | varkor <github@varkor.com> | 2018-07-24 17:47:31 +0100 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2018-08-19 20:02:34 +0100 |
| commit | e79bc410bf5f8d07121cc685d611ca72c21b28d0 (patch) | |
| tree | c9164aa1cc6d971ee706bbb68be3eae1906ecdc0 | |
| parent | ccef306b965697f01a5eb9fb69b9b7a34517cc8a (diff) | |
| download | rust-e79bc410bf5f8d07121cc685d611ca72c21b28d0.tar.gz rust-e79bc410bf5f8d07121cc685d611ca72c21b28d0.zip | |
Consolidate into create_substs_for_generic_args
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 285 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/confirm.rs | 109 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 169 |
3 files changed, 268 insertions, 295 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ccea902e4b6..83c18265489 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -14,7 +14,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::array_vec::ArrayVec; -use hir::{self, GenericArg}; +use hir::{self, GenericArg, GenericArgs}; use hir::def::Def; use hir::def_id::DefId; use middle::resolve_lifetime as rl; @@ -22,7 +22,7 @@ use namespace::Namespace; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; -use rustc::ty::GenericParamDefKind; +use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::wf::object_region_bounds; use rustc_target::spec::abi; use std::slice; @@ -192,6 +192,153 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { substs } + /// Creates the relevant generic argument substitutions + /// corresponding to a set of generic parameters. + pub fn create_substs_for_generic_args<'a, 'b, A, P, I>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + span: Span, + err_if_invalid: bool, + def_id: DefId, + parent_substs: &[Kind<'tcx>], + has_self: bool, + self_ty: Option<Ty<'tcx>>, + args_for_def_id: A, + provided_kind: P, + inferred_kind: I, + ) -> &'tcx Substs<'tcx> where + A: Fn(DefId) -> (Option<&'b GenericArgs>, bool), + P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>, + I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx> + { + // Collect the segments of the path: we need to substitute arguments + // for parameters throughout the entire path (wherever there are + // generic parameters). + let mut parent_defs = tcx.generics_of(def_id); + let count = parent_defs.count(); + let mut stack = vec![(def_id, parent_defs)]; + while let Some(def_id) = parent_defs.parent { + parent_defs = tcx.generics_of(def_id); + stack.push((def_id, parent_defs)); + } + + // We manually build up the substitution, rather than using convenience + // methods in subst.rs so that we can iterate over the arguments and + // parameters in lock-step linearly, rather than trying to match each pair. + let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 { + AccumulateVec::Array(ArrayVec::new()) + } else { + AccumulateVec::Heap(Vec::with_capacity(count)) + }; + + fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) { + match substs { + AccumulateVec::Array(ref mut arr) => arr.push(kind), + AccumulateVec::Heap(ref mut vec) => vec.push(kind), + } + } + + // Iterate over each segment of the path. + while let Some((def_id, defs)) = stack.pop() { + let mut params = defs.params.iter(); + let mut next_param = params.next(); + + // If we have already computed substitutions for parents, we can use those directly. + while let Some(param) = next_param { + if let Some(&kind) = parent_substs.get(param.index as usize) { + push_kind(&mut substs, kind); + next_param = params.next(); + } else { + break; + } + } + + // (Unless it's been handled in `parent_substs`) `Self` is handled first. + if has_self { + if let Some(param) = next_param { + if param.index == 0 { + if let GenericParamDefKind::Type { .. } = param.kind { + push_kind(&mut substs, self_ty.map(|ty| ty.into()) + .unwrap_or_else(|| inferred_kind(None, param, true))); + next_param = params.next(); + } + } + } + } + + // Check whether this segment takes generic arguments and the user has provided any. + let (generic_args, infer_types) = args_for_def_id(def_id); + if let Some(ref generic_args) = generic_args { + // We're going to iterate through the generic arguments that the user + // provided, matching them with the generic parameters we expect. + // Mismatches can occur as a result of elided lifetimes, or for malformed + // input. We try to handle both sensibly. + 'args: for arg in &generic_args.args { + while let Some(param) = next_param { + match param.kind { + GenericParamDefKind::Lifetime => match arg { + GenericArg::Lifetime(_) => { + push_kind(&mut substs, provided_kind(param, arg)); + next_param = params.next(); + continue 'args; + } + GenericArg::Type(_) => { + // We expected a lifetime argument, but got a type + // argument. That means we're inferring the lifetimes. + push_kind(&mut substs, inferred_kind(None, param, infer_types)); + next_param = params.next(); + } + } + GenericParamDefKind::Type { .. } => match arg { + GenericArg::Type(_) => { + push_kind(&mut substs, provided_kind(param, arg)); + next_param = params.next(); + continue 'args; + } + GenericArg::Lifetime(_) => { + // We expected a type argument, but got a lifetime + // argument. This is an error, but we need to handle it + // gracefully so we can report sensible errors. In this + // case, we're simply going to infer the remaining + // arguments. + if err_if_invalid { + tcx.sess.delay_span_bug(span, + "found a GenericArg::Lifetime where a \ + GenericArg::Type was expected"); + } + break 'args; + } + } + } + } + // We should never be able to reach this point with well-formed input. + // Getting to this point means the user supplied more arguments than + // there are parameters. + if err_if_invalid { + tcx.sess.delay_span_bug(span, + "GenericArg did not have matching GenericParamDef"); + } + } + } + + // If there are fewer arguments than parameters, it means + // we're inferring the remaining arguments. + while let Some(param) = next_param { + match param.kind { + GenericParamDefKind::Lifetime => { + push_kind(&mut substs, inferred_kind(None, param, infer_types)); + } + GenericParamDefKind::Type { .. } => { + let kind = inferred_kind(Some(&substs), param, infer_types); + push_kind(&mut substs, kind); + } + } + next_param = params.next(); + } + } + + tcx.intern_substs(&substs) + } + /// Given the type/region arguments provided to some path (along with /// an implicit Self, if this is a trait reference) returns the complete /// set of substitutions. This may involve applying defaulted type parameters. @@ -271,95 +418,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { false }; - // Collect the segments of the path: we need to substitute arguments - // for parameters throughout the entire path (wherever there are - // generic parameters). - let mut parent_defs = self.tcx().generics_of(def_id); - let count = parent_defs.count(); - let mut stack = vec![(def_id, parent_defs)]; - while let Some(def_id) = parent_defs.parent { - parent_defs = self.tcx().generics_of(def_id); - stack.push((def_id, parent_defs)); - } - - // We manually build up the substitution, rather than using convenience - // methods in subst.rs so that we can iterate over the arguments and - // parameters in lock-step linearly, rather than trying to match each pair. - let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 { - AccumulateVec::Array(ArrayVec::new()) - } else { - AccumulateVec::Heap(Vec::with_capacity(count)) - }; - fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) { - match substs { - AccumulateVec::Array(ref mut arr) => arr.push(kind), - AccumulateVec::Heap(ref mut vec) => vec.push(kind), - } - } - - // Iterate over each segment of the path. - while let Some((_, defs)) = stack.pop() { - let mut params = defs.params.iter(); - let mut next_param = params.next(); - - // `Self` is handled first. - if let Some(ty) = self_ty { - if let Some(param) = next_param { - if param.index == 0 { - if let GenericParamDefKind::Type { .. } = param.kind { - push_kind(&mut substs, ty.into()); - next_param = params.next(); + let substs = Self::create_substs_for_generic_args( + self.tcx(), + span, + false, + def_id, + &[][..], + self_ty.is_some(), + self_ty, + // Provide the generic args, and whether types should be inferred. + |_| (Some(generic_args), infer_types), + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match param.kind { + GenericParamDefKind::Lifetime => match arg { + GenericArg::Lifetime(lt) => { + self.ast_region_to_region(<, Some(param)).into() } + _ => unreachable!(), } - } - } - - let args = &generic_args.args; - 'args: for arg in args { - while let Some(param) = next_param { - match param.kind { - GenericParamDefKind::Lifetime => match arg { - GenericArg::Lifetime(lt) => { - push_kind(&mut substs, - self.ast_region_to_region(<, Some(param)).into()); - next_param = params.next(); - continue 'args; - } - GenericArg::Type(_) => { - // We expected a lifetime argument, but got a type - // argument. That means we're inferring the lifetimes. - push_kind(&mut substs, tcx.types.re_static.into()); - next_param = params.next(); - } - } - GenericParamDefKind::Type { .. } => match arg { - GenericArg::Type(ty) => { - push_kind(&mut substs, self.ast_ty_to_ty(&ty).into()); - next_param = params.next(); - continue 'args; - } - GenericArg::Lifetime(_) => { - break 'args; - } - } + GenericParamDefKind::Type { .. } => match arg { + GenericArg::Type(ty) => self.ast_ty_to_ty(&ty).into(), + _ => unreachable!(), } } - } - - while let Some(param) = next_param { + }, + // Provide substitutions for parameters for which arguments are inferred. + |substs, param, infer_types| { match param.kind { - GenericParamDefKind::Lifetime => { - push_kind(&mut substs, tcx.types.re_static.into()); - } + GenericParamDefKind::Lifetime => tcx.types.re_static.into(), GenericParamDefKind::Type { has_default, .. } => { - if infer_types { - // No type parameters were provided, we can infer all. - push_kind(&mut substs, if !default_needs_object_self(param) { - self.ty_infer_for_def(param, span).into() - } else { - self.ty_infer(span).into() - }); - } else if has_default { + if !infer_types && has_default { // No type parameter provided, but a default exists. // If we are converting an object type, then the @@ -378,26 +467,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { type parameters must be specified on object \ types")) .emit(); - push_kind(&mut substs, tcx.types.err.into()); + tcx.types.err.into() } else { // This is a default type parameter. - let kind = self.normalize_ty( + self.normalize_ty( span, tcx.at(span).type_of(param.def_id) - .subst_spanned(tcx, &substs, Some(span)) - ).into(); - push_kind(&mut substs, kind); + .subst_spanned(tcx, substs.unwrap(), Some(span)) + ).into() + } + } else if infer_types { + // No type parameters were provided, we can infer all. + if !default_needs_object_self(param) { + self.ty_infer_for_def(param, span).into() + } else { + self.ty_infer(span).into() } } else { // We've already errored above about the mismatch. - push_kind(&mut substs, tcx.types.err.into()); + tcx.types.err.into() } } - }; - next_param = params.next(); - } - } - let substs = self.tcx().intern_substs(&substs); + } + }, + ); let assoc_bindings = generic_args.bindings.iter().map(|binding| { ConvertedBinding { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 401e57f3157..0acbd803103 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -14,7 +14,7 @@ use astconv::AstConv; use check::{FnCtxt, PlaceOp, callee, Needs}; use hir::GenericArg; use hir::def_id::DefId; -use rustc::ty::subst::{Kind, Substs}; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, GenericParamDefKind}; use rustc::ty::subst::Subst; @@ -24,8 +24,6 @@ use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk}; use syntax_pos::Span; use rustc::hir; -use rustc_data_structures::accumulate_vec::AccumulateVec; -use rustc_data_structures::array_vec::ArrayVec; use std::ops::Deref; @@ -325,86 +323,41 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. assert_eq!(method_generics.parent_count, parent_substs.len()); - // Collect the segments of the path: we need to substitute arguments - // for parameters throughout the entire path (wherever there are - // generic parameters). - let def_id = pick.item.def_id; - let mut parent_defs = self.tcx.generics_of(def_id); - let count = parent_defs.count(); - let mut stack = vec![(def_id, parent_defs)]; - while let Some(def_id) = parent_defs.parent { - parent_defs = self.tcx.generics_of(def_id); - stack.push((def_id, parent_defs)); - } - - // We manually build up the substitution, rather than using convenience - // methods in subst.rs so that we can iterate over the arguments and - // parameters in lock-step linearly, rather than trying to match each pair. - let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 { - AccumulateVec::Array(ArrayVec::new()) - } else { - AccumulateVec::Heap(Vec::with_capacity(count)) - }; - fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) { - match substs { - AccumulateVec::Array(ref mut arr) => arr.push(kind), - AccumulateVec::Heap(ref mut vec) => vec.push(kind), - } - } - - // Iterate over each segment of the path. - while let Some((_, defs)) = stack.pop() { - let mut params = defs.params.iter(); - let mut next_param = params.next(); - - while let Some(param) = next_param { - if let Some(&kind) = parent_substs.get(param.index as usize) { - push_kind(&mut substs, kind); - next_param = params.next(); + AstConv::create_substs_for_generic_args( + self.tcx, + self.span, + false, + pick.item.def_id, + parent_substs, + false, + None, + // Provide the generic args, and whether types should be inferred. + |_| { + // The last argument of the returned tuple here is unimportant. + if let Some(ref data) = segment.args { + (Some(data), false) } else { - break; + (None, false) } - } - - if let Some(ref data) = segment.args { - let args = &data.args; - 'args: for arg in args { - while let Some(param) = next_param { - match param.kind { - GenericParamDefKind::Lifetime => match arg { - GenericArg::Lifetime(lt) => { - push_kind(&mut substs, AstConv::ast_region_to_region( - self.fcx, lt, Some(param)).into()); - next_param = params.next(); - continue 'args; - } - _ => { - push_kind(&mut substs, self.var_for_def(self.span, param)); - next_param = params.next(); - } - } - GenericParamDefKind::Type { .. } => match arg { - GenericArg::Type(ty) => { - push_kind(&mut substs, self.to_ty(ty).into()); - next_param = params.next(); - continue 'args; - } - _ => { - break 'args; - } - } + }, + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match param.kind { + GenericParamDefKind::Lifetime => match arg { + GenericArg::Lifetime(lt) => { + AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into() } + _ => unreachable!(), + } + GenericParamDefKind::Type { .. } => match arg { + GenericArg::Type(ty) => self.to_ty(ty).into(), + _ => unreachable!(), } } - } - - while let Some(param) = next_param { - push_kind(&mut substs, self.var_for_def(self.span, param)); - next_param = params.next(); - } - } - - self.tcx.intern_substs(&substs) + }, + // Provide substitutions for parameters for which arguments are inferred. + |_, param, _| self.var_for_def(self.span, param), + ) } fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1ef296774ea..141d0aea462 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,7 +95,7 @@ use rustc::infer::anon_types::AnonTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{GlobalId}; -use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs}; +use rustc::ty::subst::{UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; @@ -103,8 +103,6 @@ use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; use rustc::ty::util::{Representability, IntTypeExt, Discr}; use errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_data_structures::accumulate_vec::AccumulateVec; -use rustc_data_structures::array_vec::ArrayVec; use require_c_abi_if_variadic; use session::{CompileIncomplete, config, Session}; @@ -4282,8 +4280,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { match *qpath { hir::QPath::Resolved(ref maybe_qself, ref path) => { - let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); - let ty = AstConv::def_to_ty(self, opt_self_ty, path, true); + let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); + let ty = AstConv::def_to_ty(self, self_ty, path, true); (path.def, ty) } hir::QPath::TypeRelative(ref qself, ref segment) => { @@ -4873,7 +4871,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // number of type parameters and type. pub fn instantiate_value_path(&self, segments: &[hir::PathSegment], - opt_self_ty: Option<Ty<'tcx>>, + self_ty: Option<Ty<'tcx>>, def: Def, span: Span, node_id: ast::NodeId) @@ -4898,7 +4896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if segments.len() == 1 { // `<T>::assoc` will end up here, and so can `T::assoc`. - let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); + let self_ty = self_ty.expect("UFCS sugared assoc missing Self"); ufcs_associated = Some((container, self_ty)); } } @@ -4955,122 +4953,54 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.generics_of(*def_id).has_self }).unwrap_or(false); - // Collect the segments of the path: we need to substitute arguments - // for parameters throughout the entire path (wherever there are - // generic parameters). let def_id = def.def_id(); - let mut parent_defs = self.tcx.generics_of(def_id); - let count = parent_defs.count(); - let mut stack = vec![(def_id, parent_defs)]; - while let Some(def_id) = parent_defs.parent { - parent_defs = self.tcx.generics_of(def_id); - stack.push((def_id, parent_defs)); - } - // We manually build up the substitution, rather than using convenience - // methods in subst.rs so that we can iterate over the arguments and - // parameters in lock-step linearly, rather than trying to match each pair. - let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 { - AccumulateVec::Array(ArrayVec::new()) - } else { - AccumulateVec::Heap(Vec::with_capacity(count)) - }; - fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) { - match substs { - AccumulateVec::Array(ref mut arr) => arr.push(kind), - AccumulateVec::Heap(ref mut vec) => vec.push(kind), - } - } - - // Iterate over each segment of the path. - while let Some((def_id, defs)) = stack.pop() { - let mut params = defs.params.iter(); - let mut next_param = params.next(); - - // `Self` is handled first. - if has_self { - if let Some(param) = next_param { - if param.index == 0 { - if let GenericParamDefKind::Type { .. } = param.kind { - push_kind(&mut substs, opt_self_ty.map(|ty| ty.into()) - .unwrap_or_else(|| self.var_for_def(span, param))); - next_param = params.next(); + let substs = AstConv::create_substs_for_generic_args( + self.tcx, + span, + true, + def_id, + &[][..], + has_self, + self_ty, + // Provide the generic args, and whether types should be inferred. + |def_id| { + if let Some(&PathSeg(_, index)) = path_segs.iter().find(|&PathSeg(did, _)| { + *did == def_id + }) { + // If we've encountered an `impl Trait`-related error, we're just + // going to infer the arguments for better error messages. + if !supress_errors[&index] { + // Check whether the user has provided generic arguments. + if let Some(ref data) = segments[index].args { + return (Some(data), segments[index].infer_types); } } + return (None, segments[index].infer_types); } - } - let mut infer_types = true; - // Check whether this segment takes generic arguments. - if let Some(&PathSeg(_, index)) = path_segs - .iter() - .find(|&PathSeg(did, _)| *did == def_id) { - // If we've encountered an `impl Trait`-related error, we're just - // going to infer the arguments for better error messages. - if !supress_errors[&index] { - infer_types = segments[index].infer_types; - // Check whether the user has provided generic arguments. - if let Some(ref data) = segments[index].args { - let args = &data.args; - // We're going to iterate through the generic arguments that the user - // provided, matching them with the generic parameters we expect. - // Mismatches can occur as a result of elided lifetimes, or for malformed - // input. We try to handle both sensibly. - 'args: for arg in args { - while let Some(param) = next_param { - match param.kind { - GenericParamDefKind::Lifetime => match arg { - GenericArg::Lifetime(lt) => { - push_kind(&mut substs, - AstConv::ast_region_to_region(self, lt, Some(param)) - .into()); - next_param = params.next(); - continue 'args; - } - GenericArg::Type(_) => { - // We expected a lifetime argument, but got a type - // argument. That means we're inferring the lifetimes. - push_kind(&mut substs, - self.re_infer(span, Some(param)).unwrap().into()); - next_param = params.next(); - } - } - GenericParamDefKind::Type { .. } => match arg { - GenericArg::Type(ty) => { - push_kind(&mut substs, self.to_ty(ty).into()); - next_param = params.next(); - continue 'args; - } - GenericArg::Lifetime(_) => { - // We expected a type argument, but got a lifetime - // argument. This is an error, but we need to handle it - // gracefully so we can report sensible errors. In this - // case, we're simply going to infer the remaining - // arguments. - self.tcx.sess.delay_span_bug(span, - "found a GenericArg::Lifetime where a \ - GenericArg::Type was expected"); - break 'args; - } - } - } - } - // We should never be able to reach this point with well-formed input. - // Getting to this point means the user supplied more arguments than - // there are parameters. - self.tcx.sess.delay_span_bug(span, - "GenericArg did not have matching GenericParamDef"); + (None, true) + }, + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match param.kind { + GenericParamDefKind::Lifetime => match arg { + GenericArg::Lifetime(lt) => { + AstConv::ast_region_to_region(self, lt, Some(param)).into() } + _ => unreachable!(), + } + GenericParamDefKind::Type { .. } => match arg { + GenericArg::Type(ty) => self.to_ty(ty).into(), + _ => unreachable!(), } } - } - - // If there are fewer arguments than parameters, it means - // we're inferring the remaining arguments. - while let Some(param) = next_param { + }, + // Provide substitutions for parameters for which arguments are inferred. + |substs, param, infer_types| { match param.kind { GenericParamDefKind::Lifetime => { - push_kind(&mut substs, self.re_infer(span, Some(param)).unwrap().into()); + self.re_infer(span, Some(param)).unwrap().into() } GenericParamDefKind::Type { has_default, .. } => { if !infer_types && has_default { @@ -5078,24 +5008,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // inferring the type arguments: we provide the default where any // is missing. let default = self.tcx.type_of(param.def_id); - let kind = self.normalize_ty( + self.normalize_ty( span, - default.subst_spanned(self.tcx, &substs, Some(span)) - ).into(); - push_kind(&mut substs, kind); + default.subst_spanned(self.tcx, substs.unwrap(), Some(span)) + ).into() } else { // If no type arguments were provided, we have to infer them. // This case also occurs as a result of some malformed input, e.g. // a lifetime argument being given instead of a type paramter. // Using inference instead of `TyError` gives better error messages. - push_kind(&mut substs, self.var_for_def(span, param)); + self.var_for_def(span, param) } } } - next_param = params.next(); - } - } - let substs = self.tcx.intern_substs(&substs); + }, + ); // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. |
