Skip to content

Commit 00396cb

Browse files
Rollup merge of #79019 - lcnr:generic-arg-validation, r=petrochenkov
astconv: extract closures into a separate trait Am currently looking into completely removing `check_generic_arg_count` and `create_substs_for_generic_args` was somewhat difficult to understand for me so I moved these closures into a trait. This should not have changed the behavior of any of these methods
2 parents f66af28 + 894b1f7 commit 00396cb

File tree

4 files changed

+292
-178
lines changed

4 files changed

+292
-178
lines changed

compiler/rustc_typeck/src/astconv/generics.rs

+10-15
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use crate::astconv::{
2-
AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
2+
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
3+
GenericArgCountResult, GenericArgPosition,
34
};
45
use crate::errors::AssocTypeBindingNotAllowed;
56
use rustc_ast::ast::ParamKindOrd;
67
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
78
use rustc_hir as hir;
89
use rustc_hir::def_id::DefId;
9-
use rustc_hir::{GenericArg, GenericArgs};
10+
use rustc_hir::GenericArg;
1011
use rustc_middle::ty::{
1112
self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
1213
};
@@ -90,20 +91,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9091
/// instantiate a `GenericArg`.
9192
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
9293
/// creates a suitable inference variable.
93-
pub fn create_substs_for_generic_args<'b>(
94+
pub fn create_substs_for_generic_args<'a>(
9495
tcx: TyCtxt<'tcx>,
9596
def_id: DefId,
9697
parent_substs: &[subst::GenericArg<'tcx>],
9798
has_self: bool,
9899
self_ty: Option<Ty<'tcx>>,
99100
arg_count: GenericArgCountResult,
100-
args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
101-
mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
102-
mut inferred_kind: impl FnMut(
103-
Option<&[subst::GenericArg<'tcx>]>,
104-
&GenericParamDef,
105-
bool,
106-
) -> subst::GenericArg<'tcx>,
101+
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
107102
) -> SubstsRef<'tcx> {
108103
// Collect the segments of the path; we need to substitute arguments
109104
// for parameters throughout the entire path (wherever there are
@@ -142,7 +137,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
142137
substs.push(
143138
self_ty
144139
.map(|ty| ty.into())
145-
.unwrap_or_else(|| inferred_kind(None, param, true)),
140+
.unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
146141
);
147142
params.next();
148143
}
@@ -151,7 +146,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
151146
}
152147

153148
// Check whether this segment takes generic arguments and the user has provided any.
154-
let (generic_args, infer_args) = args_for_def_id(def_id);
149+
let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
155150

156151
let mut args =
157152
generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
@@ -173,7 +168,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
173168
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
174169
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
175170
| (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
176-
substs.push(provided_kind(param, arg));
171+
substs.push(ctx.provided_kind(param, arg));
177172
args.next();
178173
params.next();
179174
}
@@ -184,7 +179,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
184179
) => {
185180
// We expected a lifetime argument, but got a type or const
186181
// argument. That means we're inferring the lifetimes.
187-
substs.push(inferred_kind(None, param, infer_args));
182+
substs.push(ctx.inferred_kind(None, param, infer_args));
188183
force_infer_lt = Some(arg);
189184
params.next();
190185
}
@@ -302,7 +297,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
302297
(None, Some(&param)) => {
303298
// If there are fewer arguments than parameters, it means
304299
// we're inferring the remaining arguments.
305-
substs.push(inferred_kind(Some(&substs), param, infer_args));
300+
substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
306301
params.next();
307302
}
308303

compiler/rustc_typeck/src/astconv/mod.rs

+143-81
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ pub struct GenericArgCountResult {
165165
pub correct: Result<(), GenericArgCountMismatch>,
166166
}
167167

168+
pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
169+
fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool);
170+
171+
fn provided_kind(
172+
&mut self,
173+
param: &ty::GenericParamDef,
174+
arg: &GenericArg<'_>,
175+
) -> subst::GenericArg<'tcx>;
176+
177+
fn inferred_kind(
178+
&mut self,
179+
substs: Option<&[subst::GenericArg<'tcx>]>,
180+
param: &ty::GenericParamDef,
181+
infer_args: bool,
182+
) -> subst::GenericArg<'tcx>;
183+
}
184+
168185
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
169186
pub fn ast_region_to_region(
170187
&self,
@@ -321,81 +338,102 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
321338
);
322339

323340
let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
324-
let default_needs_object_self = |param: &ty::GenericParamDef| {
325-
if let GenericParamDefKind::Type { has_default, .. } = param.kind {
326-
if is_object && has_default {
327-
let default_ty = tcx.at(span).type_of(param.def_id);
328-
let self_param = tcx.types.self_param;
329-
if default_ty.walk().any(|arg| arg == self_param.into()) {
330-
// There is no suitable inference default for a type parameter
331-
// that references self, in an object type.
332-
return true;
341+
342+
struct SubstsForAstPathCtxt<'a, 'tcx> {
343+
astconv: &'a (dyn AstConv<'tcx> + 'a),
344+
def_id: DefId,
345+
generic_args: &'a GenericArgs<'a>,
346+
span: Span,
347+
missing_type_params: Vec<String>,
348+
inferred_params: Vec<Span>,
349+
infer_args: bool,
350+
is_object: bool,
351+
}
352+
353+
impl<'tcx, 'a> SubstsForAstPathCtxt<'tcx, 'a> {
354+
fn default_needs_object_self(&mut self, param: &ty::GenericParamDef) -> bool {
355+
let tcx = self.astconv.tcx();
356+
if let GenericParamDefKind::Type { has_default, .. } = param.kind {
357+
if self.is_object && has_default {
358+
let default_ty = tcx.at(self.span).type_of(param.def_id);
359+
let self_param = tcx.types.self_param;
360+
if default_ty.walk().any(|arg| arg == self_param.into()) {
361+
// There is no suitable inference default for a type parameter
362+
// that references self, in an object type.
363+
return true;
364+
}
333365
}
334366
}
335-
}
336367

337-
false
338-
};
368+
false
369+
}
370+
}
339371

340-
let mut missing_type_params = vec![];
341-
let mut inferred_params = vec![];
342-
let substs = Self::create_substs_for_generic_args(
343-
tcx,
344-
def_id,
345-
parent_substs,
346-
self_ty.is_some(),
347-
self_ty,
348-
arg_count.clone(),
349-
// Provide the generic args, and whether types should be inferred.
350-
|did| {
351-
if did == def_id {
352-
(Some(generic_args), infer_args)
372+
impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
373+
fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) {
374+
if did == self.def_id {
375+
(Some(self.generic_args), self.infer_args)
353376
} else {
354377
// The last component of this tuple is unimportant.
355378
(None, false)
356379
}
357-
},
358-
// Provide substitutions for parameters for which (valid) arguments have been provided.
359-
|param, arg| match (&param.kind, arg) {
360-
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
361-
self.ast_region_to_region(&lt, Some(param)).into()
362-
}
363-
(GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
364-
if *has_default {
365-
tcx.check_optional_stability(
366-
param.def_id,
367-
Some(arg.id()),
368-
arg.span(),
369-
|_, _| {
370-
// Default generic parameters may not be marked
371-
// with stability attributes, i.e. when the
372-
// default parameter was defined at the same time
373-
// as the rest of the type. As such, we ignore missing
374-
// stability attributes.
380+
}
381+
382+
fn provided_kind(
383+
&mut self,
384+
param: &ty::GenericParamDef,
385+
arg: &GenericArg<'_>,
386+
) -> subst::GenericArg<'tcx> {
387+
let tcx = self.astconv.tcx();
388+
match (&param.kind, arg) {
389+
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
390+
self.astconv.ast_region_to_region(&lt, Some(param)).into()
391+
}
392+
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
393+
if has_default {
394+
tcx.check_optional_stability(
395+
param.def_id,
396+
Some(arg.id()),
397+
arg.span(),
398+
|_, _| {
399+
// Default generic parameters may not be marked
400+
// with stability attributes, i.e. when the
401+
// default parameter was defined at the same time
402+
// as the rest of the type. As such, we ignore missing
403+
// stability attributes.
404+
},
405+
)
406+
}
407+
if let (hir::TyKind::Infer, false) =
408+
(&ty.kind, self.astconv.allow_ty_infer())
409+
{
410+
self.inferred_params.push(ty.span);
411+
tcx.ty_error().into()
412+
} else {
413+
self.astconv.ast_ty_to_ty(&ty).into()
414+
}
415+
}
416+
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
417+
ty::Const::from_opt_const_arg_anon_const(
418+
tcx,
419+
ty::WithOptConstParam {
420+
did: tcx.hir().local_def_id(ct.value.hir_id),
421+
const_param_did: Some(param.def_id),
375422
},
376423
)
424+
.into()
377425
}
378-
if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
379-
inferred_params.push(ty.span);
380-
tcx.ty_error().into()
381-
} else {
382-
self.ast_ty_to_ty(&ty).into()
383-
}
384-
}
385-
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
386-
ty::Const::from_opt_const_arg_anon_const(
387-
tcx,
388-
ty::WithOptConstParam {
389-
did: tcx.hir().local_def_id(ct.value.hir_id),
390-
const_param_did: Some(param.def_id),
391-
},
392-
)
393-
.into()
426+
_ => unreachable!(),
394427
}
395-
_ => unreachable!(),
396-
},
397-
// Provide substitutions for parameters for which arguments are inferred.
398-
|substs, param, infer_args| {
428+
}
429+
430+
fn inferred_kind(
431+
&mut self,
432+
substs: Option<&[subst::GenericArg<'tcx>]>,
433+
param: &ty::GenericParamDef,
434+
infer_args: bool,
435+
) -> subst::GenericArg<'tcx> {
436+
let tcx = self.astconv.tcx();
399437
match param.kind {
400438
GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
401439
GenericParamDefKind::Type { has_default, .. } => {
@@ -407,48 +445,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
407445
// other type parameters may reference `Self` in their
408446
// defaults. This will lead to an ICE if we are not
409447
// careful!
410-
if default_needs_object_self(param) {
411-
missing_type_params.push(param.name.to_string());
448+
if self.default_needs_object_self(param) {
449+
self.missing_type_params.push(param.name.to_string());
412450
tcx.ty_error().into()
413451
} else {
414452
// This is a default type parameter.
415-
self.normalize_ty(
416-
span,
417-
tcx.at(span).type_of(param.def_id).subst_spanned(
418-
tcx,
419-
substs.unwrap(),
420-
Some(span),
421-
),
422-
)
423-
.into()
453+
self.astconv
454+
.normalize_ty(
455+
self.span,
456+
tcx.at(self.span).type_of(param.def_id).subst_spanned(
457+
tcx,
458+
substs.unwrap(),
459+
Some(self.span),
460+
),
461+
)
462+
.into()
424463
}
425464
} else if infer_args {
426465
// No type parameters were provided, we can infer all.
427-
let param =
428-
if !default_needs_object_self(param) { Some(param) } else { None };
429-
self.ty_infer(param, span).into()
466+
let param = if !self.default_needs_object_self(param) {
467+
Some(param)
468+
} else {
469+
None
470+
};
471+
self.astconv.ty_infer(param, self.span).into()
430472
} else {
431473
// We've already errored above about the mismatch.
432474
tcx.ty_error().into()
433475
}
434476
}
435477
GenericParamDefKind::Const => {
436-
let ty = tcx.at(span).type_of(param.def_id);
478+
let ty = tcx.at(self.span).type_of(param.def_id);
437479
// FIXME(const_generics:defaults)
438480
if infer_args {
439481
// No const parameters were provided, we can infer all.
440-
self.ct_infer(ty, Some(param), span).into()
482+
self.astconv.ct_infer(ty, Some(param), self.span).into()
441483
} else {
442484
// We've already errored above about the mismatch.
443485
tcx.const_error(ty).into()
444486
}
445487
}
446488
}
447-
},
489+
}
490+
}
491+
492+
let mut substs_ctx = SubstsForAstPathCtxt {
493+
astconv: self,
494+
def_id,
495+
span,
496+
generic_args,
497+
missing_type_params: vec![],
498+
inferred_params: vec![],
499+
infer_args,
500+
is_object,
501+
};
502+
let substs = Self::create_substs_for_generic_args(
503+
tcx,
504+
def_id,
505+
parent_substs,
506+
self_ty.is_some(),
507+
self_ty,
508+
arg_count.clone(),
509+
&mut substs_ctx,
448510
);
449511

450512
self.complain_about_missing_type_params(
451-
missing_type_params,
513+
substs_ctx.missing_type_params,
452514
def_id,
453515
span,
454516
generic_args.args.is_empty(),

0 commit comments

Comments
 (0)