Skip to content

Commit fd853c0

Browse files
committed
Auto merge of #83484 - JulianKnodt:infer, r=oli-obk,lcnr
Add hir::GenericArg::Infer In order to extend inference to consts, make an Infer type on hir::GenericArg.
2 parents 3bc9dd0 + 8759f00 commit fd853c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+524
-108
lines changed

compiler/rustc_ast/src/ast.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,17 @@ 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.
341+
Infer,
339342
}
340343

341344
impl Ord for ParamKindOrd {
342345
fn cmp(&self, other: &Self) -> Ordering {
343346
use ParamKindOrd::*;
344347
let to_int = |v| match v {
345348
Lifetime => 0,
346-
Type | Const { unordered: true } => 1,
349+
Infer | Type | Const { unordered: true } => 1,
347350
// technically both consts should be ordered equally,
348351
// but only one is ever encountered at a time, so this is
349352
// fine.
@@ -371,6 +374,7 @@ impl fmt::Display for ParamKindOrd {
371374
ParamKindOrd::Lifetime => "lifetime".fmt(f),
372375
ParamKindOrd::Type => "type".fmt(f),
373376
ParamKindOrd::Const { .. } => "const".fmt(f),
377+
ParamKindOrd::Infer => "infer".fmt(f),
374378
}
375379
}
376380
}

compiler/rustc_ast_lowering/src/lib.rs

+52-41
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};
@@ -1243,48 +1243,59 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12431243
match arg {
12441244
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
12451245
ast::GenericArg::Type(ty) => {
1246-
// We parse const arguments as path types as we cannot distinguish them during
1247-
// parsing. We try to resolve that ambiguity by attempting resolution in both the
1248-
// type and value namespaces. If we resolved the path in the value namespace, we
1249-
// transform it into a generic const argument.
1250-
if let TyKind::Path(ref qself, ref path) = ty.kind {
1251-
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
1252-
let res = partial_res.base_res();
1253-
if !res.matches_ns(Namespace::TypeNS) {
1254-
debug!(
1255-
"lower_generic_arg: Lowering type argument as const argument: {:?}",
1256-
ty,
1257-
);
1258-
1259-
// Construct a AnonConst where the expr is the "ty"'s path.
1260-
1261-
let parent_def_id = self.current_hir_id_owner.0;
1262-
let node_id = self.resolver.next_node_id();
1263-
1264-
// Add a definition for the in-band const def.
1265-
self.resolver.create_def(
1266-
parent_def_id,
1267-
node_id,
1268-
DefPathData::AnonConst,
1269-
ExpnId::root(),
1270-
ty.span,
1271-
);
1272-
1273-
let path_expr = Expr {
1274-
id: ty.id,
1275-
kind: ExprKind::Path(qself.clone(), path.clone()),
1276-
span: ty.span,
1277-
attrs: AttrVec::new(),
1278-
tokens: None,
1279-
};
1280-
1281-
let ct = self.with_new_scopes(|this| hir::AnonConst {
1282-
hir_id: this.lower_node_id(node_id),
1283-
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
1284-
});
1285-
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
1246+
match ty.kind {
1247+
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
1248+
let hir_id = self.lower_node_id(ty.id);
1249+
return GenericArg::Infer(hir::InferArg {
1250+
hir_id,
1251+
span: ty.span,
1252+
kind: InferKind::Type,
1253+
});
1254+
}
1255+
// We parse const arguments as path types as we cannot distinguish them during
1256+
// parsing. We try to resolve that ambiguity by attempting resolution in both the
1257+
// type and value namespaces. If we resolved the path in the value namespace, we
1258+
// transform it into a generic const argument.
1259+
TyKind::Path(ref qself, ref path) => {
1260+
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
1261+
let res = partial_res.base_res();
1262+
if !res.matches_ns(Namespace::TypeNS) {
1263+
debug!(
1264+
"lower_generic_arg: Lowering type argument as const argument: {:?}",
1265+
ty,
1266+
);
1267+
1268+
// Construct a AnonConst where the expr is the "ty"'s path.
1269+
1270+
let parent_def_id = self.current_hir_id_owner.0;
1271+
let node_id = self.resolver.next_node_id();
1272+
1273+
// Add a definition for the in-band const def.
1274+
self.resolver.create_def(
1275+
parent_def_id,
1276+
node_id,
1277+
DefPathData::AnonConst,
1278+
ExpnId::root(),
1279+
ty.span,
1280+
);
1281+
1282+
let path_expr = Expr {
1283+
id: ty.id,
1284+
kind: ExprKind::Path(qself.clone(), path.clone()),
1285+
span: ty.span,
1286+
attrs: AttrVec::new(),
1287+
tokens: None,
1288+
};
1289+
1290+
let ct = self.with_new_scopes(|this| hir::AnonConst {
1291+
hir_id: this.lower_node_id(node_id),
1292+
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
1293+
});
1294+
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
1295+
}
12861296
}
12871297
}
1298+
_ => {}
12881299
}
12891300
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
12901301
}

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,9 @@ declare_features! (
680680
/// Allows `cfg(target_abi = "...")`.
681681
(active, cfg_target_abi, "1.55.0", Some(80970), None),
682682

683+
/// Infer generic args for both consts and types.
684+
(active, generic_arg_infer, "1.55.0", Some(85077), None),
685+
683686
// -------------------------------------------------------------------------
684687
// feature-group-end: actual feature gates
685688
// -------------------------------------------------------------------------

compiler/rustc_hir/src/hir.rs

+57-13
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,38 @@ pub struct ConstArg {
254254
pub span: Span,
255255
}
256256

257+
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
258+
pub enum InferKind {
259+
Const,
260+
Type,
261+
}
262+
263+
impl InferKind {
264+
#[inline]
265+
pub fn is_type(self) -> bool {
266+
matches!(self, InferKind::Type)
267+
}
268+
}
269+
270+
#[derive(Encodable, Debug, HashStable_Generic)]
271+
pub struct InferArg {
272+
pub hir_id: HirId,
273+
pub kind: InferKind,
274+
pub span: Span,
275+
}
276+
277+
impl InferArg {
278+
pub fn to_ty(&self) -> Ty<'_> {
279+
Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id }
280+
}
281+
}
282+
257283
#[derive(Debug, HashStable_Generic)]
258284
pub enum GenericArg<'hir> {
259285
Lifetime(Lifetime),
260286
Type(Ty<'hir>),
261287
Const(ConstArg),
288+
Infer(InferArg),
262289
}
263290

264291
impl GenericArg<'_> {
@@ -267,6 +294,7 @@ impl GenericArg<'_> {
267294
GenericArg::Lifetime(l) => l.span,
268295
GenericArg::Type(t) => t.span,
269296
GenericArg::Const(c) => c.span,
297+
GenericArg::Infer(i) => i.span,
270298
}
271299
}
272300

@@ -275,6 +303,7 @@ impl GenericArg<'_> {
275303
GenericArg::Lifetime(l) => l.hir_id,
276304
GenericArg::Type(t) => t.hir_id,
277305
GenericArg::Const(c) => c.value.hir_id,
306+
GenericArg::Infer(i) => i.hir_id,
278307
}
279308
}
280309

@@ -291,6 +320,7 @@ impl GenericArg<'_> {
291320
GenericArg::Lifetime(_) => "lifetime",
292321
GenericArg::Type(_) => "type",
293322
GenericArg::Const(_) => "constant",
323+
GenericArg::Infer(_) => "inferred",
294324
}
295325
}
296326

@@ -301,6 +331,7 @@ impl GenericArg<'_> {
301331
GenericArg::Const(_) => {
302332
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
303333
}
334+
GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
304335
}
305336
}
306337
}
@@ -342,27 +373,36 @@ impl GenericArgs<'_> {
342373
break;
343374
}
344375
GenericArg::Const(_) => {}
376+
GenericArg::Infer(_) => {}
345377
}
346378
}
347379
}
348380
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
349381
}
350382

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

357-
for arg in self.args {
358-
match arg {
359-
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
360-
GenericArg::Type(_) => own_counts.types += 1,
361-
GenericArg::Const(_) => own_counts.consts += 1,
362-
};
363-
}
388+
#[inline]
389+
pub fn num_type_params(&self) -> usize {
390+
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
391+
}
364392

365-
own_counts
393+
#[inline]
394+
pub fn num_lifetime_params(&self) -> usize {
395+
self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
396+
}
397+
398+
#[inline]
399+
pub fn has_lifetime_params(&self) -> bool {
400+
self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
401+
}
402+
403+
#[inline]
404+
pub fn num_generic_params(&self) -> usize {
405+
self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
366406
}
367407

368408
/// The span encompassing the text inside the surrounding brackets.
@@ -485,6 +525,7 @@ pub struct GenericParamCount {
485525
pub lifetimes: usize,
486526
pub types: usize,
487527
pub consts: usize,
528+
pub infer: usize,
488529
}
489530

490531
/// Represents lifetimes and type parameters attached to a declaration
@@ -3130,6 +3171,8 @@ pub enum Node<'hir> {
31303171
Visibility(&'hir Visibility<'hir>),
31313172

31323173
Crate(&'hir Mod<'hir>),
3174+
3175+
Infer(&'hir InferArg),
31333176
}
31343177

31353178
impl<'hir> Node<'hir> {
@@ -3198,6 +3241,7 @@ impl<'hir> Node<'hir> {
31983241
| Node::Local(Local { hir_id, .. })
31993242
| Node::Lifetime(Lifetime { hir_id, .. })
32003243
| Node::Param(Param { hir_id, .. })
3244+
| Node::Infer(InferArg { hir_id, .. })
32013245
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
32023246
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
32033247
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,

compiler/rustc_hir/src/intravisit.rs

+8
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,15 @@ pub trait Visitor<'v>: Sized {
436436
fn visit_label(&mut self, label: &'v Label) {
437437
walk_label(self, label)
438438
}
439+
fn visit_infer(&mut self, inf: &'v InferArg) {
440+
walk_inf(self, inf);
441+
}
439442
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
440443
match generic_arg {
441444
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
442445
GenericArg::Type(ty) => self.visit_ty(ty),
443446
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
447+
GenericArg::Infer(inf) => self.visit_infer(inf),
444448
}
445449
}
446450
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
@@ -747,6 +751,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
747751
}
748752
}
749753

754+
pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
755+
visitor.visit_id(inf.hir_id);
756+
}
757+
750758
pub fn walk_qpath<'v, V: Visitor<'v>>(
751759
visitor: &mut V,
752760
qpath: &'v QPath<'v>,

compiler/rustc_hir_pretty/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -103,6 +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.s.word("_"),
106107
Node::Block(a) => {
107108
// Containing cbox, will be closed by print-block at `}`.
108109
self.cbox(INDENT_UNIT);
@@ -437,14 +438,14 @@ impl<'a> State<'a> {
437438
self.print_anon_const(e);
438439
self.s.word(")");
439440
}
440-
hir::TyKind::Infer => {
441-
self.s.word("_");
442-
}
443441
hir::TyKind::Err => {
444442
self.popen();
445443
self.s.word("/*ERROR*/");
446444
self.pclose();
447445
}
446+
hir::TyKind::Infer => {
447+
self.s.word("_");
448+
}
448449
}
449450
self.end()
450451
}
@@ -1851,6 +1852,7 @@ impl<'a> State<'a> {
18511852
GenericArg::Lifetime(_) => {}
18521853
GenericArg::Type(ty) => s.print_type(ty),
18531854
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
1855+
GenericArg::Infer(_inf) => s.word("_"),
18541856
},
18551857
);
18561858
}

compiler/rustc_lint/src/late.rs

+5
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
244244
hir_visit::walk_ty(self, t);
245245
}
246246

247+
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
248+
lint_callback!(self, check_infer, inf);
249+
hir_visit::walk_inf(self, inf);
250+
}
251+
247252
fn visit_name(&mut self, sp: Span, name: Symbol) {
248253
lint_callback!(self, check_name, sp, name);
249254
}

compiler/rustc_lint/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ macro_rules! late_lint_methods {
3333
fn check_expr(a: &$hir hir::Expr<$hir>);
3434
fn check_expr_post(a: &$hir hir::Expr<$hir>);
3535
fn check_ty(a: &$hir hir::Ty<$hir>);
36+
fn check_infer(a: &$hir hir::InferArg);
3637
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
3738
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
3839
fn check_generics(a: &$hir hir::Generics<$hir>);

compiler/rustc_middle/src/hir/map/collector.rs

+8
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
336336
});
337337
}
338338

339+
fn visit_infer(&mut self, inf: &'hir InferArg) {
340+
self.insert(inf.span, inf.hir_id, Node::Infer(inf));
341+
342+
self.with_parent(inf.hir_id, |this| {
343+
intravisit::walk_inf(this, inf);
344+
});
345+
}
346+
339347
fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
340348
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
341349

0 commit comments

Comments
 (0)