about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-11-13 15:49:17 +0100
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-11-13 15:49:17 +0100
commit894b1f7d3d508bb644e01c62dfb983a394380fd3 (patch)
tree49f46cd578a2ed0ead9cf8ffdc02a27ccfb9c65b
parent2c4df6bb343e89c382ae2301505013132af77319 (diff)
downloadrust-894b1f7d3d508bb644e01c62dfb983a394380fd3.tar.gz
rust-894b1f7d3d508bb644e01c62dfb983a394380fd3.zip
extract closures into a separate trait
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs25
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs224
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs147
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs74
4 files changed, 292 insertions, 178 deletions
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 3bfb2d3f1b0..301ede66006 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -1,12 +1,13 @@
 use crate::astconv::{
-    AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
+    AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
+    GenericArgCountResult, GenericArgPosition,
 };
 use crate::errors::AssocTypeBindingNotAllowed;
 use rustc_ast::ast::ParamKindOrd;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{GenericArg, GenericArgs};
+use rustc_hir::GenericArg;
 use rustc_middle::ty::{
     self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
 };
@@ -90,20 +91,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     ///   instantiate a `GenericArg`.
     /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
     ///   creates a suitable inference variable.
-    pub fn create_substs_for_generic_args<'b>(
+    pub fn create_substs_for_generic_args<'a>(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
         parent_substs: &[subst::GenericArg<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
         arg_count: GenericArgCountResult,
-        args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
-        mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
-        mut inferred_kind: impl FnMut(
-            Option<&[subst::GenericArg<'tcx>]>,
-            &GenericParamDef,
-            bool,
-        ) -> subst::GenericArg<'tcx>,
+        ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
     ) -> SubstsRef<'tcx> {
         // Collect the segments of the path; we need to substitute arguments
         // for parameters throughout the entire path (wherever there are
@@ -142,7 +137,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             substs.push(
                                 self_ty
                                     .map(|ty| ty.into())
-                                    .unwrap_or_else(|| inferred_kind(None, param, true)),
+                                    .unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
                             );
                             params.next();
                         }
@@ -151,7 +146,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
 
             // Check whether this segment takes generic arguments and the user has provided any.
-            let (generic_args, infer_args) = args_for_def_id(def_id);
+            let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
 
             let mut args =
                 generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
@@ -173,7 +168,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
                             | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
                             | (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
-                                substs.push(provided_kind(param, arg));
+                                substs.push(ctx.provided_kind(param, arg));
                                 args.next();
                                 params.next();
                             }
@@ -184,7 +179,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             ) => {
                                 // We expected a lifetime argument, but got a type or const
                                 // argument. That means we're inferring the lifetimes.
-                                substs.push(inferred_kind(None, param, infer_args));
+                                substs.push(ctx.inferred_kind(None, param, infer_args));
                                 force_infer_lt = Some(arg);
                                 params.next();
                             }
@@ -302,7 +297,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     (None, Some(&param)) => {
                         // If there are fewer arguments than parameters, it means
                         // we're inferring the remaining arguments.
-                        substs.push(inferred_kind(Some(&substs), param, infer_args));
+                        substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
                         params.next();
                     }
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 07e523af3eb..89c5adfa14c 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -165,6 +165,23 @@ pub struct GenericArgCountResult {
     pub correct: Result<(), GenericArgCountMismatch>,
 }
 
+pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
+    fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool);
+
+    fn provided_kind(
+        &mut self,
+        param: &ty::GenericParamDef,
+        arg: &GenericArg<'_>,
+    ) -> subst::GenericArg<'tcx>;
+
+    fn inferred_kind(
+        &mut self,
+        substs: Option<&[subst::GenericArg<'tcx>]>,
+        param: &ty::GenericParamDef,
+        infer_args: bool,
+    ) -> subst::GenericArg<'tcx>;
+}
+
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub fn ast_region_to_region(
         &self,
@@ -321,81 +338,102 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         );
 
         let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
-        let default_needs_object_self = |param: &ty::GenericParamDef| {
-            if let GenericParamDefKind::Type { has_default, .. } = param.kind {
-                if is_object && has_default {
-                    let default_ty = tcx.at(span).type_of(param.def_id);
-                    let self_param = tcx.types.self_param;
-                    if default_ty.walk().any(|arg| arg == self_param.into()) {
-                        // There is no suitable inference default for a type parameter
-                        // that references self, in an object type.
-                        return true;
+
+        struct SubstsForAstPathCtxt<'a, 'tcx> {
+            astconv: &'a (dyn AstConv<'tcx> + 'a),
+            def_id: DefId,
+            generic_args: &'a GenericArgs<'a>,
+            span: Span,
+            missing_type_params: Vec<String>,
+            inferred_params: Vec<Span>,
+            infer_args: bool,
+            is_object: bool,
+        }
+
+        impl<'tcx, 'a> SubstsForAstPathCtxt<'tcx, 'a> {
+            fn default_needs_object_self(&mut self, param: &ty::GenericParamDef) -> bool {
+                let tcx = self.astconv.tcx();
+                if let GenericParamDefKind::Type { has_default, .. } = param.kind {
+                    if self.is_object && has_default {
+                        let default_ty = tcx.at(self.span).type_of(param.def_id);
+                        let self_param = tcx.types.self_param;
+                        if default_ty.walk().any(|arg| arg == self_param.into()) {
+                            // There is no suitable inference default for a type parameter
+                            // that references self, in an object type.
+                            return true;
+                        }
                     }
                 }
-            }
 
-            false
-        };
+                false
+            }
+        }
 
-        let mut missing_type_params = vec![];
-        let mut inferred_params = vec![];
-        let substs = Self::create_substs_for_generic_args(
-            tcx,
-            def_id,
-            parent_substs,
-            self_ty.is_some(),
-            self_ty,
-            arg_count.clone(),
-            // Provide the generic args, and whether types should be inferred.
-            |did| {
-                if did == def_id {
-                    (Some(generic_args), infer_args)
+        impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
+            fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) {
+                if did == self.def_id {
+                    (Some(self.generic_args), self.infer_args)
                 } else {
                     // The last component of this tuple is unimportant.
                     (None, false)
                 }
-            },
-            // Provide substitutions for parameters for which (valid) arguments have been provided.
-            |param, arg| match (&param.kind, arg) {
-                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                    self.ast_region_to_region(&lt, Some(param)).into()
-                }
-                (GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
-                    if *has_default {
-                        tcx.check_optional_stability(
-                            param.def_id,
-                            Some(arg.id()),
-                            arg.span(),
-                            |_, _| {
-                                // Default generic parameters may not be marked
-                                // with stability attributes, i.e. when the
-                                // default parameter was defined at the same time
-                                // as the rest of the type. As such, we ignore missing
-                                // stability attributes.
+            }
+
+            fn provided_kind(
+                &mut self,
+                param: &ty::GenericParamDef,
+                arg: &GenericArg<'_>,
+            ) -> subst::GenericArg<'tcx> {
+                let tcx = self.astconv.tcx();
+                match (&param.kind, arg) {
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                        self.astconv.ast_region_to_region(&lt, Some(param)).into()
+                    }
+                    (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
+                        if has_default {
+                            tcx.check_optional_stability(
+                                param.def_id,
+                                Some(arg.id()),
+                                arg.span(),
+                                |_, _| {
+                                    // Default generic parameters may not be marked
+                                    // with stability attributes, i.e. when the
+                                    // default parameter was defined at the same time
+                                    // as the rest of the type. As such, we ignore missing
+                                    // stability attributes.
+                                },
+                            )
+                        }
+                        if let (hir::TyKind::Infer, false) =
+                            (&ty.kind, self.astconv.allow_ty_infer())
+                        {
+                            self.inferred_params.push(ty.span);
+                            tcx.ty_error().into()
+                        } else {
+                            self.astconv.ast_ty_to_ty(&ty).into()
+                        }
+                    }
+                    (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+                        ty::Const::from_opt_const_arg_anon_const(
+                            tcx,
+                            ty::WithOptConstParam {
+                                did: tcx.hir().local_def_id(ct.value.hir_id),
+                                const_param_did: Some(param.def_id),
                             },
                         )
+                        .into()
                     }
-                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
-                        inferred_params.push(ty.span);
-                        tcx.ty_error().into()
-                    } else {
-                        self.ast_ty_to_ty(&ty).into()
-                    }
-                }
-                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    ty::Const::from_opt_const_arg_anon_const(
-                        tcx,
-                        ty::WithOptConstParam {
-                            did: tcx.hir().local_def_id(ct.value.hir_id),
-                            const_param_did: Some(param.def_id),
-                        },
-                    )
-                    .into()
+                    _ => unreachable!(),
                 }
-                _ => unreachable!(),
-            },
-            // Provide substitutions for parameters for which arguments are inferred.
-            |substs, param, infer_args| {
+            }
+
+            fn inferred_kind(
+                &mut self,
+                substs: Option<&[subst::GenericArg<'tcx>]>,
+                param: &ty::GenericParamDef,
+                infer_args: bool,
+            ) -> subst::GenericArg<'tcx> {
+                let tcx = self.astconv.tcx();
                 match param.kind {
                     GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
                     GenericParamDefKind::Type { has_default, .. } => {
@@ -407,48 +445,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             // other type parameters may reference `Self` in their
                             // defaults. This will lead to an ICE if we are not
                             // careful!
-                            if default_needs_object_self(param) {
-                                missing_type_params.push(param.name.to_string());
+                            if self.default_needs_object_self(param) {
+                                self.missing_type_params.push(param.name.to_string());
                                 tcx.ty_error().into()
                             } else {
                                 // This is a default type parameter.
-                                self.normalize_ty(
-                                    span,
-                                    tcx.at(span).type_of(param.def_id).subst_spanned(
-                                        tcx,
-                                        substs.unwrap(),
-                                        Some(span),
-                                    ),
-                                )
-                                .into()
+                                self.astconv
+                                    .normalize_ty(
+                                        self.span,
+                                        tcx.at(self.span).type_of(param.def_id).subst_spanned(
+                                            tcx,
+                                            substs.unwrap(),
+                                            Some(self.span),
+                                        ),
+                                    )
+                                    .into()
                             }
                         } else if infer_args {
                             // No type parameters were provided, we can infer all.
-                            let param =
-                                if !default_needs_object_self(param) { Some(param) } else { None };
-                            self.ty_infer(param, span).into()
+                            let param = if !self.default_needs_object_self(param) {
+                                Some(param)
+                            } else {
+                                None
+                            };
+                            self.astconv.ty_infer(param, self.span).into()
                         } else {
                             // We've already errored above about the mismatch.
                             tcx.ty_error().into()
                         }
                     }
                     GenericParamDefKind::Const => {
-                        let ty = tcx.at(span).type_of(param.def_id);
+                        let ty = tcx.at(self.span).type_of(param.def_id);
                         // FIXME(const_generics:defaults)
                         if infer_args {
                             // No const parameters were provided, we can infer all.
-                            self.ct_infer(ty, Some(param), span).into()
+                            self.astconv.ct_infer(ty, Some(param), self.span).into()
                         } else {
                             // We've already errored above about the mismatch.
                             tcx.const_error(ty).into()
                         }
                     }
                 }
-            },
+            }
+        }
+
+        let mut substs_ctx = SubstsForAstPathCtxt {
+            astconv: self,
+            def_id,
+            span,
+            generic_args,
+            missing_type_params: vec![],
+            inferred_params: vec![],
+            infer_args,
+            is_object,
+        };
+        let substs = Self::create_substs_for_generic_args(
+            tcx,
+            def_id,
+            parent_substs,
+            self_ty.is_some(),
+            self_ty,
+            arg_count.clone(),
+            &mut substs_ctx,
         );
 
         self.complain_about_missing_type_params(
-            missing_type_params,
+            substs_ctx.missing_type_params,
             def_id,
             span,
             generic_args.args.is_empty(),
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 0bb7b464f16..300ee8f85f8 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1,5 +1,6 @@
 use crate::astconv::{
-    AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, PathSeg,
+    AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
+    GenericArgCountResult, PathSeg,
 };
 use crate::check::callee::{self, DeferredCallResolution};
 use crate::check::method::{self, MethodCallee, SelfSource};
@@ -1298,76 +1299,108 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             },
         };
 
-        let substs = self_ctor_substs.unwrap_or_else(|| {
-            AstConv::create_substs_for_generic_args(
-                tcx,
-                def_id,
-                &[][..],
-                has_self,
-                self_ty,
-                arg_count,
-                // 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 !infer_args_for_err.contains(&index) {
-                            // Check whether the user has provided generic arguments.
-                            if let Some(ref data) = segments[index].args {
-                                return (Some(data), segments[index].infer_args);
-                            }
+        struct CreateCtorSubstsContext<'a, 'tcx> {
+            fcx: &'a FnCtxt<'a, 'tcx>,
+            span: Span,
+            path_segs: &'a [PathSeg],
+            infer_args_for_err: &'a FxHashSet<usize>,
+            segments: &'a [hir::PathSegment<'a>],
+        }
+        impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> {
+            fn args_for_def_id(
+                &mut self,
+                def_id: DefId,
+            ) -> (Option<&'a hir::GenericArgs<'a>>, bool) {
+                if let Some(&PathSeg(_, index)) =
+                    self.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 !self.infer_args_for_err.contains(&index) {
+                        // Check whether the user has provided generic arguments.
+                        if let Some(ref data) = self.segments[index].args {
+                            return (Some(data), self.segments[index].infer_args);
                         }
-                        return (None, segments[index].infer_args);
                     }
+                    return (None, self.segments[index].infer_args);
+                }
 
-                    (None, true)
-                },
-                // Provide substitutions for parameters for which (valid) arguments have been provided.
-                |param, arg| match (&param.kind, arg) {
+                (None, true)
+            }
+
+            fn provided_kind(
+                &mut self,
+                param: &ty::GenericParamDef,
+                arg: &GenericArg<'_>,
+            ) -> subst::GenericArg<'tcx> {
+                match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        AstConv::ast_region_to_region(self, lt, Some(param)).into()
+                        AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
-                        self.to_ty(ty).into()
+                        self.fcx.to_ty(ty).into()
                     }
                     (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                        self.const_arg_to_const(&ct.value, param.def_id).into()
+                        self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
                     }
                     _ => unreachable!(),
-                },
-                // Provide substitutions for parameters for which arguments are inferred.
-                |substs, param, infer_args| {
-                    match param.kind {
-                        GenericParamDefKind::Lifetime => {
-                            self.re_infer(Some(param), span).unwrap().into()
-                        }
-                        GenericParamDefKind::Type { has_default, .. } => {
-                            if !infer_args && has_default {
-                                // If we have a default, then we it doesn't matter that we're not
-                                // inferring the type arguments: we provide the default where any
-                                // is missing.
-                                let default = tcx.type_of(param.def_id);
-                                self.normalize_ty(
-                                    span,
-                                    default.subst_spanned(tcx, substs.unwrap(), Some(span)),
+                }
+            }
+
+            fn inferred_kind(
+                &mut self,
+                substs: Option<&[subst::GenericArg<'tcx>]>,
+                param: &ty::GenericParamDef,
+                infer_args: bool,
+            ) -> subst::GenericArg<'tcx> {
+                let tcx = self.fcx.tcx();
+                match param.kind {
+                    GenericParamDefKind::Lifetime => {
+                        self.fcx.re_infer(Some(param), self.span).unwrap().into()
+                    }
+                    GenericParamDefKind::Type { has_default, .. } => {
+                        if !infer_args && has_default {
+                            // If we have a default, then we it doesn't matter that we're not
+                            // inferring the type arguments: we provide the default where any
+                            // is missing.
+                            let default = tcx.type_of(param.def_id);
+                            self.fcx
+                                .normalize_ty(
+                                    self.span,
+                                    default.subst_spanned(tcx, substs.unwrap(), Some(self.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 parameter.
-                                // Using inference instead of `Error` gives better error messages.
-                                self.var_for_def(span, param)
-                            }
-                        }
-                        GenericParamDefKind::Const => {
-                            // FIXME(const_generics:defaults)
-                            // No const parameters were provided, we have to infer them.
-                            self.var_for_def(span, param)
+                        } 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 parameter.
+                            // Using inference instead of `Error` gives better error messages.
+                            self.fcx.var_for_def(self.span, param)
                         }
                     }
+                    GenericParamDefKind::Const => {
+                        // FIXME(const_generics:defaults)
+                        // No const parameters were provided, we have to infer them.
+                        self.fcx.var_for_def(self.span, param)
+                    }
+                }
+            }
+        }
+
+        let substs = self_ctor_substs.unwrap_or_else(|| {
+            AstConv::create_substs_for_generic_args(
+                tcx,
+                def_id,
+                &[][..],
+                has_self,
+                self_ty,
+                arg_count,
+                &mut CreateCtorSubstsContext {
+                    fcx: self,
+                    span,
+                    path_segs: &path_segs,
+                    infer_args_for_err: &infer_args_for_err,
+                    segments,
                 },
             )
         });
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index fd2700b85e2..fb048abc0e9 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -1,6 +1,6 @@
 use super::{probe, MethodCallee};
 
-use crate::astconv::AstConv;
+use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt};
 use crate::check::{callee, FnCtxt};
 use crate::hir::def_id::DefId;
 use crate::hir::GenericArg;
@@ -10,7 +10,7 @@ use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, Subst, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits;
@@ -307,6 +307,52 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // parameters from the type and those from the method.
         assert_eq!(generics.parent_count, parent_substs.len());
 
+        struct MethodSubstsCtxt<'a, 'tcx> {
+            cfcx: &'a ConfirmContext<'a, 'tcx>,
+            pick: &'a probe::Pick<'tcx>,
+            seg: &'a hir::PathSegment<'a>,
+        }
+        impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> {
+            fn args_for_def_id(
+                &mut self,
+                def_id: DefId,
+            ) -> (Option<&'a hir::GenericArgs<'a>>, bool) {
+                if def_id == self.pick.item.def_id {
+                    if let Some(ref data) = self.seg.args {
+                        return (Some(data), false);
+                    }
+                }
+                (None, false)
+            }
+
+            fn provided_kind(
+                &mut self,
+                param: &ty::GenericParamDef,
+                arg: &GenericArg<'_>,
+            ) -> subst::GenericArg<'tcx> {
+                match (&param.kind, arg) {
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                        AstConv::ast_region_to_region(self.cfcx.fcx, lt, Some(param)).into()
+                    }
+                    (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                        self.cfcx.to_ty(ty).into()
+                    }
+                    (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+                        self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
+                    }
+                    _ => unreachable!(),
+                }
+            }
+
+            fn inferred_kind(
+                &mut self,
+                _substs: Option<&[subst::GenericArg<'tcx>]>,
+                param: &ty::GenericParamDef,
+                _infer_args: bool,
+            ) -> subst::GenericArg<'tcx> {
+                self.cfcx.var_for_def(self.cfcx.span, param)
+            }
+        }
         AstConv::create_substs_for_generic_args(
             self.tcx,
             pick.item.def_id,
@@ -314,29 +360,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             false,
             None,
             arg_count_correct,
-            // Provide the generic args, and whether types should be inferred.
-            |def_id| {
-                // The last component of the returned tuple here is unimportant.
-                if def_id == pick.item.def_id {
-                    if let Some(ref data) = seg.args {
-                        return (Some(data), false);
-                    }
-                }
-                (None, false)
-            },
-            // Provide substitutions for parameters for which (valid) arguments have been provided.
-            |param, arg| match (&param.kind, arg) {
-                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                    AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
-                }
-                (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => self.to_ty(ty).into(),
-                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    self.const_arg_to_const(&ct.value, param.def_id).into()
-                }
-                _ => unreachable!(),
-            },
-            // Provide substitutions for parameters for which arguments are inferred.
-            |_, param, _| self.var_for_def(self.span, param),
+            &mut MethodSubstsCtxt { cfcx: self, pick, seg },
         )
     }