Skip to content

Commit 8759f00

Browse files
committed
Actually infer args in visitors
1 parent 3605675 commit 8759f00

30 files changed

+257
-97
lines changed

compiler/rustc_ast/src/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ pub enum ParamKindOrd {
336336
// is active. Specifically, if it's only `min_const_generics`, it will still require
337337
// ordering consts after types.
338338
Const { unordered: bool },
339+
// `Infer` is not actually constructed directly from the AST, but is implicitly constructed
340+
// during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
339341
Infer,
340342
}
341343

compiler/rustc_ast_lowering/src/lib.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
5151
use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID};
5252
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
5353
use rustc_hir::intravisit;
54-
use rustc_hir::{ConstArg, GenericArg, ParamName};
54+
use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName};
5555
use rustc_index::vec::{Idx, IndexVec};
5656
use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
5757
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
@@ -1219,9 +1219,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12191219
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
12201220
ast::GenericArg::Type(ty) => {
12211221
match ty.kind {
1222-
TyKind::Infer => {
1222+
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
12231223
let hir_id = self.lower_node_id(ty.id);
1224-
return GenericArg::Infer(hir::InferArg { hir_id, span: ty.span });
1224+
return GenericArg::Infer(hir::InferArg {
1225+
hir_id,
1226+
span: ty.span,
1227+
kind: InferKind::Type,
1228+
});
12251229
}
12261230
// We parse const arguments as path types as we cannot distinguish them during
12271231
// parsing. We try to resolve that ambiguity by attempting resolution in both the

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,9 @@ declare_features! (
684684
/// Allows `cfg(target_abi = "...")`.
685685
(active, cfg_target_abi, "1.55.0", Some(80970), None),
686686

687+
/// Infer generic args for both consts and types.
688+
(active, generic_arg_infer, "1.55.0", Some(85077), None),
689+
687690
// -------------------------------------------------------------------------
688691
// feature-group-end: actual feature gates
689692
// -------------------------------------------------------------------------

compiler/rustc_hir/src/hir.rs

+35-14
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,23 @@ pub struct ConstArg {
253253
pub span: Span,
254254
}
255255

256+
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
257+
pub enum InferKind {
258+
Const,
259+
Type,
260+
}
261+
262+
impl InferKind {
263+
#[inline]
264+
pub fn is_type(self) -> bool {
265+
matches!(self, InferKind::Type)
266+
}
267+
}
268+
256269
#[derive(Encodable, Debug, HashStable_Generic)]
257270
pub struct InferArg {
258271
pub hir_id: HirId,
272+
pub kind: InferKind,
259273
pub span: Span,
260274
}
261275

@@ -365,22 +379,29 @@ impl GenericArgs<'_> {
365379
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
366380
}
367381

368-
pub fn own_counts(&self) -> GenericParamCount {
369-
// We could cache this as a property of `GenericParamCount`, but
370-
// the aim is to refactor this away entirely eventually and the
371-
// presence of this method will be a constant reminder.
372-
let mut own_counts: GenericParamCount = Default::default();
382+
#[inline]
383+
pub fn has_type_params(&self) -> bool {
384+
self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_)))
385+
}
373386

374-
for arg in self.args {
375-
match arg {
376-
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
377-
GenericArg::Type(_) => own_counts.types += 1,
378-
GenericArg::Const(_) => own_counts.consts += 1,
379-
GenericArg::Infer(_) => own_counts.infer += 1,
380-
};
381-
}
387+
#[inline]
388+
pub fn num_type_params(&self) -> usize {
389+
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
390+
}
391+
392+
#[inline]
393+
pub fn num_lifetime_params(&self) -> usize {
394+
self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
395+
}
382396

383-
own_counts
397+
#[inline]
398+
pub fn has_lifetime_params(&self) -> bool {
399+
self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
400+
}
401+
402+
#[inline]
403+
pub fn num_generic_params(&self) -> usize {
404+
self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
384405
}
385406

386407
/// The span encompassing the text inside the surrounding brackets.

compiler/rustc_hir_pretty/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl<'a> State<'a> {
103103
Node::TraitRef(a) => self.print_trait_ref(&a),
104104
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
105105
Node::Arm(a) => self.print_arm(&a),
106-
Node::Infer(_) => self.print_string("_", ast::StrStyle::Cooked),
106+
Node::Infer(_) => self.s.word("_"),
107107
Node::Block(a) => {
108108
// Containing cbox, will be closed by print-block at `}`.
109109
self.cbox(INDENT_UNIT);

compiler/rustc_privacy/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12241224
}
12251225
}
12261226
} else {
1227+
let local_id = self.tcx.hir().local_def_id(inf.hir_id);
1228+
if let Some(did) = self.tcx.opt_const_param_of(local_id) {
1229+
if self.visit_def_id(did, "inferred", &"").is_break() {
1230+
return;
1231+
}
1232+
}
1233+
12271234
// FIXME see above note for same issue.
12281235
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() {
12291236
return;

compiler/rustc_resolve/src/late/lifetimes.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2559,7 +2559,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25592559
}
25602560
GenericArg::Infer(inf) => {
25612561
self.visit_id(inf.hir_id);
2562-
i += 1;
2562+
if inf.kind.is_type() {
2563+
i += 1;
2564+
}
25632565
}
25642566
}
25652567
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ symbols! {
622622
generator,
623623
generator_state,
624624
generators,
625+
generic_arg_infer,
625626
generic_associated_types,
626627
generic_param_attrs,
627628
get_context,

compiler/rustc_typeck/src/astconv/generics.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3939
);
4040

4141
if let GenericParamDefKind::Const { .. } = param.kind {
42-
if matches!(
43-
arg,
44-
GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) | GenericArg::Infer(_)
45-
) {
42+
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
4643
err.help("const arguments cannot yet be inferred with `_`");
44+
if sess.is_nightly_build() {
45+
err.help(
46+
"add `#![feature(generic_arg_infer)]` to the crate attributes to enable",
47+
);
48+
}
4749
}
4850
}
4951

@@ -458,8 +460,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
458460
let default_counts = gen_params.own_defaults();
459461
let param_counts = gen_params.own_counts();
460462
let named_type_param_count = param_counts.types - has_self as usize;
461-
let arg_counts = gen_args.own_counts();
462-
let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0;
463+
let infer_lifetimes =
464+
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
463465

464466
if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
465467
Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
@@ -517,7 +519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
517519

518520
let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
519521
let max_expected_lifetime_args = param_counts.lifetimes;
520-
let num_provided_lifetime_args = arg_counts.lifetimes;
522+
let num_provided_lifetime_args = gen_args.num_lifetime_params();
521523

522524
let lifetimes_correct = check_lifetime_args(
523525
min_expected_lifetime_args,
@@ -588,14 +590,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
588590
- default_counts.consts
589591
};
590592
debug!("expected_min: {:?}", expected_min);
591-
debug!("arg_counts.lifetimes: {:?}", arg_counts.lifetimes);
593+
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
592594

593595
check_types_and_consts(
594596
expected_min,
595597
param_counts.consts + named_type_param_count,
596-
arg_counts.consts + arg_counts.types + arg_counts.infer,
598+
gen_args.num_generic_params(),
597599
param_counts.lifetimes + has_self as usize,
598-
arg_counts.lifetimes,
600+
gen_args.num_lifetime_params(),
599601
)
600602
};
601603

@@ -673,8 +675,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
673675
position: GenericArgPosition,
674676
) -> ExplicitLateBound {
675677
let param_counts = def.own_counts();
676-
let arg_counts = args.own_counts();
677-
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
678+
let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params();
678679

679680
if infer_lifetimes {
680681
return ExplicitLateBound::No;
@@ -687,7 +688,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
687688
let span = args.args[0].span();
688689

689690
if position == GenericArgPosition::Value
690-
&& arg_counts.lifetimes != param_counts.lifetimes
691+
&& args.num_lifetime_params() != param_counts.lifetimes
691692
{
692693
let mut err = tcx.sess.struct_span_err(span, msg);
693694
err.span_note(span_late, note);

compiler/rustc_typeck/src/astconv/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
463463
}
464464
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
465465
if has_default {
466-
// FIXME(const_generics): Actually infer parameter here?
467466
tcx.const_param_default(param.def_id).into()
467+
} else if self.astconv.allow_ty_infer() {
468+
// FIXME(const_generics): Actually infer parameter here?
469+
todo!()
468470
} else {
469471
self.inferred_params.push(inf.span);
470472
tcx.ty_error().into()
@@ -1963,7 +1965,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
19631965
}
19641966
has_err = true;
19651967
err_for_ty = true;
1966-
(inf.span, "inferred")
1968+
(inf.span, "generic")
19671969
}
19681970
};
19691971
let mut err = struct_span_err!(

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1480,10 +1480,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14801480
self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
14811481
}
14821482
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
1483-
self.fcx.to_ty(&inf.to_ty()).into()
1483+
self.fcx.ty_infer(Some(param), inf.span).into()
14841484
}
14851485
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
1486-
self.fcx.var_for_def(inf.span, param)
1486+
let tcx = self.fcx.tcx();
1487+
self.fcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
14871488
}
14881489
_ => unreachable!(),
14891490
}

compiler/rustc_typeck/src/check/method/confirm.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
367367
self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
368368
}
369369
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
370-
self.cfcx.to_ty(&inf.to_ty()).into()
370+
self.cfcx.ty_infer(Some(param), inf.span).into()
371371
}
372372
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
373-
self.cfcx.var_for_def(inf.span, param)
373+
let tcx = self.cfcx.tcx();
374+
self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
374375
}
375376
_ => unreachable!(),
376377
}

compiler/rustc_typeck/src/collect/type_of.rs

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty};
2020
///
2121
/// This should be called using the query `tcx.opt_const_param_of`.
2222
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
23+
// FIXME(generic_arg_infer): allow for returning DefIds of inference of
24+
// GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag
25+
// for const or type.
2326
use hir::*;
2427
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
2528

src/test/ui/const-generics/issues/issue-62878.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// revisions: full min
2-
#![cfg_attr(full, feature(const_generics))]
2+
#![cfg_attr(full, feature(const_generics, generic_arg_infer))]
33
#![cfg_attr(full, allow(incomplete_features))]
44

55
fn foo<const N: usize, const A: [u8; N]>() {}

src/test/ui/const-generics/min_const_generics/inferred_const.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(generic_arg_infer)]
12
// run-pass
23

34
fn foo<const N: usize, const K: usize>(_data: [u32; N]) -> [u32; K] {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0747]: type provided when a constant was expected
2+
--> $DIR/feature-gate-generic_arg_infer.rs:11:20
3+
|
4+
LL | let _x = foo::<_>([1,2]);
5+
| ^
6+
|
7+
= help: const arguments cannot yet be inferred with `_`
8+
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0747`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// [feature] run-pass
2+
// revisions: normal feature
3+
4+
#![cfg_attr(feature, feature(generic_arg_infer))]
5+
6+
fn foo<const N: usize>(_: [u8; N]) -> [u8; N] {
7+
[0; N]
8+
}
9+
10+
fn main() {
11+
let _x = foo::<_>([1,2]);
12+
//[normal]~^ ERROR: type provided when a constant was expected
13+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(generic_arg_infer)]
2+
3+
struct All<'a, T, const N: usize> {
4+
v: &'a T,
5+
}
6+
7+
struct BadInfer<_>;
8+
//~^ ERROR expected identifier
9+
//~| ERROR parameter `_` is never used
10+
11+
fn all_fn<'a, T, const N: usize>() {}
12+
13+
fn bad_infer_fn<_>() {}
14+
//~^ ERROR expected identifier
15+
16+
17+
fn main() {
18+
let a: All<_, _, _>;
19+
all_fn();
20+
let v: [u8; _];
21+
//~^ ERROR in expressions
22+
let v: [u8; 10] = [0; _];
23+
//~^ ERROR in expressions
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error: expected identifier, found reserved identifier `_`
2+
--> $DIR/infer-arg-test.rs:7:17
3+
|
4+
LL | struct BadInfer<_>;
5+
| ^ expected identifier, found reserved identifier
6+
7+
error: expected identifier, found reserved identifier `_`
8+
--> $DIR/infer-arg-test.rs:13:17
9+
|
10+
LL | fn bad_infer_fn<_>() {}
11+
| ^ expected identifier, found reserved identifier
12+
13+
error: in expressions, `_` can only be used on the left-hand side of an assignment
14+
--> $DIR/infer-arg-test.rs:20:15
15+
|
16+
LL | let v: [u8; _];
17+
| ^ `_` not allowed here
18+
19+
error: in expressions, `_` can only be used on the left-hand side of an assignment
20+
--> $DIR/infer-arg-test.rs:22:25
21+
|
22+
LL | let v: [u8; 10] = [0; _];
23+
| ^ `_` not allowed here
24+
25+
error[E0392]: parameter `_` is never used
26+
--> $DIR/infer-arg-test.rs:7:17
27+
|
28+
LL | struct BadInfer<_>;
29+
| ^ unused parameter
30+
|
31+
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
32+
= help: if you intended `_` to be a const parameter, use `const _: usize` instead
33+
34+
error: aborting due to 5 previous errors
35+
36+
For more information about this error, try `rustc --explain E0392`.

0 commit comments

Comments
 (0)