extract closures into a separate trait
This commit is contained in:
parent
2c4df6bb34
commit
894b1f7d3d
@ -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 @@ fn generic_arg_mismatch_err(
|
||||
/// 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 @@ pub fn create_substs_for_generic_args<'b>(
|
||||
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 @@ pub fn create_substs_for_generic_args<'b>(
|
||||
}
|
||||
|
||||
// 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 @@ pub fn create_substs_for_generic_args<'b>(
|
||||
(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 @@ pub fn create_substs_for_generic_args<'b>(
|
||||
) => {
|
||||
// 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 @@ pub fn create_substs_for_generic_args<'b>(
|
||||
(None, Some(¶m)) => {
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@ -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 @@ fn create_substs_for_ast_path<'a>(
|
||||
);
|
||||
|
||||
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 (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
self.ast_region_to_region(<, 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 (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
self.astconv.ast_region_to_region(<, 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()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
(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!(),
|
||||
},
|
||||
// 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 @@ fn create_substs_for_ast_path<'a>(
|
||||
// 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(),
|
||||
|
@ -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,6 +1299,94 @@ pub fn instantiate_value_path(
|
||||
},
|
||||
};
|
||||
|
||||
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, self.segments[index].infer_args);
|
||||
}
|
||||
|
||||
(None, true)
|
||||
}
|
||||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'_>,
|
||||
) -> subst::GenericArg<'tcx> {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.fcx.to_ty(ty).into()
|
||||
}
|
||||
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
|
||||
self.fcx.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> {
|
||||
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.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,
|
||||
@ -1306,68 +1395,12 @@ pub fn instantiate_value_path(
|
||||
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);
|
||||
}
|
||||
}
|
||||
return (None, segments[index].infer_args);
|
||||
}
|
||||
|
||||
(None, true)
|
||||
},
|
||||
// Provide substitutions for parameters for which (valid) arguments have been provided.
|
||||
|param, arg| match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
AstConv::ast_region_to_region(self, 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.
|
||||
|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)),
|
||||
)
|
||||
.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)
|
||||
}
|
||||
}
|
||||
&mut CreateCtorSubstsContext {
|
||||
fcx: self,
|
||||
span,
|
||||
path_segs: &path_segs,
|
||||
infer_args_for_err: &infer_args_for_err,
|
||||
segments,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
@ -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::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 @@ fn instantiate_method_substs(
|
||||
// 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 (¶m.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 @@ fn instantiate_method_substs(
|
||||
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 (¶m.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 },
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user