Skip to content

Commit

Permalink
Auto merge of #83484 - JulianKnodt:infer, r=oli-obk,lcnr
Browse files Browse the repository at this point in the history
Add hir::GenericArg::Infer

In order to extend inference to consts, make an Infer type on hir::GenericArg.
  • Loading branch information
bors committed Jul 27, 2021
2 parents 3bc9dd0 + 8759f00 commit fd853c0
Show file tree
Hide file tree
Showing 44 changed files with 524 additions and 108 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,17 @@ pub enum ParamKindOrd {
// is active. Specifically, if it's only `min_const_generics`, it will still require
// ordering consts after types.
Const { unordered: bool },
// `Infer` is not actually constructed directly from the AST, but is implicitly constructed
// during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
Infer,
}

impl Ord for ParamKindOrd {
fn cmp(&self, other: &Self) -> Ordering {
use ParamKindOrd::*;
let to_int = |v| match v {
Lifetime => 0,
Type | Const { unordered: true } => 1,
Infer | Type | Const { unordered: true } => 1,
// technically both consts should be ordered equally,
// but only one is ever encountered at a time, so this is
// fine.
Expand Down Expand Up @@ -371,6 +374,7 @@ impl fmt::Display for ParamKindOrd {
ParamKindOrd::Lifetime => "lifetime".fmt(f),
ParamKindOrd::Type => "type".fmt(f),
ParamKindOrd::Const { .. } => "const".fmt(f),
ParamKindOrd::Infer => "infer".fmt(f),
}
}
}
Expand Down
93 changes: 52 additions & 41 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::intravisit;
use rustc_hir::{ConstArg, GenericArg, ParamName};
use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName};
use rustc_index::vec::{Idx, IndexVec};
use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
Expand Down Expand Up @@ -1243,48 +1243,59 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
ast::GenericArg::Type(ty) => {
// We parse const arguments as path types as we cannot distinguish them during
// parsing. We try to resolve that ambiguity by attempting resolution in both the
// type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument.
if let TyKind::Path(ref qself, ref path) = ty.kind {
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
let res = partial_res.base_res();
if !res.matches_ns(Namespace::TypeNS) {
debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}",
ty,
);

// Construct a AnonConst where the expr is the "ty"'s path.

let parent_def_id = self.current_hir_id_owner.0;
let node_id = self.resolver.next_node_id();

// Add a definition for the in-band const def.
self.resolver.create_def(
parent_def_id,
node_id,
DefPathData::AnonConst,
ExpnId::root(),
ty.span,
);

let path_expr = Expr {
id: ty.id,
kind: ExprKind::Path(qself.clone(), path.clone()),
span: ty.span,
attrs: AttrVec::new(),
tokens: None,
};

let ct = self.with_new_scopes(|this| hir::AnonConst {
hir_id: this.lower_node_id(node_id),
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
});
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
match ty.kind {
TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
let hir_id = self.lower_node_id(ty.id);
return GenericArg::Infer(hir::InferArg {
hir_id,
span: ty.span,
kind: InferKind::Type,
});
}
// We parse const arguments as path types as we cannot distinguish them during
// parsing. We try to resolve that ambiguity by attempting resolution in both the
// type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument.
TyKind::Path(ref qself, ref path) => {
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
let res = partial_res.base_res();
if !res.matches_ns(Namespace::TypeNS) {
debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}",
ty,
);

// Construct a AnonConst where the expr is the "ty"'s path.

let parent_def_id = self.current_hir_id_owner.0;
let node_id = self.resolver.next_node_id();

// Add a definition for the in-band const def.
self.resolver.create_def(
parent_def_id,
node_id,
DefPathData::AnonConst,
ExpnId::root(),
ty.span,
);

let path_expr = Expr {
id: ty.id,
kind: ExprKind::Path(qself.clone(), path.clone()),
span: ty.span,
attrs: AttrVec::new(),
tokens: None,
};

let ct = self.with_new_scopes(|this| hir::AnonConst {
hir_id: this.lower_node_id(node_id),
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
});
return GenericArg::Const(ConstArg { value: ct, span: ty.span });
}
}
}
_ => {}
}
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,9 @@ declare_features! (
/// Allows `cfg(target_abi = "...")`.
(active, cfg_target_abi, "1.55.0", Some(80970), None),

/// Infer generic args for both consts and types.
(active, generic_arg_infer, "1.55.0", Some(85077), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
70 changes: 57 additions & 13 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,38 @@ pub struct ConstArg {
pub span: Span,
}

#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub enum InferKind {
Const,
Type,
}

impl InferKind {
#[inline]
pub fn is_type(self) -> bool {
matches!(self, InferKind::Type)
}
}

#[derive(Encodable, Debug, HashStable_Generic)]
pub struct InferArg {
pub hir_id: HirId,
pub kind: InferKind,
pub span: Span,
}

impl InferArg {
pub fn to_ty(&self) -> Ty<'_> {
Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id }
}
}

#[derive(Debug, HashStable_Generic)]
pub enum GenericArg<'hir> {
Lifetime(Lifetime),
Type(Ty<'hir>),
Const(ConstArg),
Infer(InferArg),
}

impl GenericArg<'_> {
Expand All @@ -267,6 +294,7 @@ impl GenericArg<'_> {
GenericArg::Lifetime(l) => l.span,
GenericArg::Type(t) => t.span,
GenericArg::Const(c) => c.span,
GenericArg::Infer(i) => i.span,
}
}

Expand All @@ -275,6 +303,7 @@ impl GenericArg<'_> {
GenericArg::Lifetime(l) => l.hir_id,
GenericArg::Type(t) => t.hir_id,
GenericArg::Const(c) => c.value.hir_id,
GenericArg::Infer(i) => i.hir_id,
}
}

Expand All @@ -291,6 +320,7 @@ impl GenericArg<'_> {
GenericArg::Lifetime(_) => "lifetime",
GenericArg::Type(_) => "type",
GenericArg::Const(_) => "constant",
GenericArg::Infer(_) => "inferred",
}
}

Expand All @@ -301,6 +331,7 @@ impl GenericArg<'_> {
GenericArg::Const(_) => {
ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
}
GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
}
}
}
Expand Down Expand Up @@ -342,27 +373,36 @@ impl GenericArgs<'_> {
break;
}
GenericArg::Const(_) => {}
GenericArg::Infer(_) => {}
}
}
}
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
}

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

for arg in self.args {
match arg {
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
GenericArg::Type(_) => own_counts.types += 1,
GenericArg::Const(_) => own_counts.consts += 1,
};
}
#[inline]
pub fn num_type_params(&self) -> usize {
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
}

own_counts
#[inline]
pub fn num_lifetime_params(&self) -> usize {
self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
}

#[inline]
pub fn has_lifetime_params(&self) -> bool {
self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
}

#[inline]
pub fn num_generic_params(&self) -> usize {
self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
}

/// The span encompassing the text inside the surrounding brackets.
Expand Down Expand Up @@ -485,6 +525,7 @@ pub struct GenericParamCount {
pub lifetimes: usize,
pub types: usize,
pub consts: usize,
pub infer: usize,
}

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

Crate(&'hir Mod<'hir>),

Infer(&'hir InferArg),
}

impl<'hir> Node<'hir> {
Expand Down Expand Up @@ -3198,6 +3241,7 @@ impl<'hir> Node<'hir> {
| Node::Local(Local { hir_id, .. })
| Node::Lifetime(Lifetime { hir_id, .. })
| Node::Param(Param { hir_id, .. })
| Node::Infer(InferArg { hir_id, .. })
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,15 @@ pub trait Visitor<'v>: Sized {
fn visit_label(&mut self, label: &'v Label) {
walk_label(self, label)
}
fn visit_infer(&mut self, inf: &'v InferArg) {
walk_inf(self, inf);
}
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
match generic_arg {
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
GenericArg::Type(ty) => self.visit_ty(ty),
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
GenericArg::Infer(inf) => self.visit_infer(inf),
}
}
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
Expand Down Expand Up @@ -747,6 +751,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
}
}

pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
visitor.visit_id(inf.hir_id);
}

pub fn walk_qpath<'v, V: Visitor<'v>>(
visitor: &mut V,
qpath: &'v QPath<'v>,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ impl<'a> State<'a> {
Node::TraitRef(a) => self.print_trait_ref(&a),
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
Node::Arm(a) => self.print_arm(&a),
Node::Infer(_) => self.s.word("_"),
Node::Block(a) => {
// Containing cbox, will be closed by print-block at `}`.
self.cbox(INDENT_UNIT);
Expand Down Expand Up @@ -437,14 +438,14 @@ impl<'a> State<'a> {
self.print_anon_const(e);
self.s.word(")");
}
hir::TyKind::Infer => {
self.s.word("_");
}
hir::TyKind::Err => {
self.popen();
self.s.word("/*ERROR*/");
self.pclose();
}
hir::TyKind::Infer => {
self.s.word("_");
}
}
self.end()
}
Expand Down Expand Up @@ -1851,6 +1852,7 @@ impl<'a> State<'a> {
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => s.print_type(ty),
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
GenericArg::Infer(_inf) => s.word("_"),
},
);
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
hir_visit::walk_ty(self, t);
}

fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
lint_callback!(self, check_infer, inf);
hir_visit::walk_inf(self, inf);
}

fn visit_name(&mut self, sp: Span, name: Symbol) {
lint_callback!(self, check_name, sp, name);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ macro_rules! late_lint_methods {
fn check_expr(a: &$hir hir::Expr<$hir>);
fn check_expr_post(a: &$hir hir::Expr<$hir>);
fn check_ty(a: &$hir hir::Ty<$hir>);
fn check_infer(a: &$hir hir::InferArg);
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
fn check_generics(a: &$hir hir::Generics<$hir>);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}

fn visit_infer(&mut self, inf: &'hir InferArg) {
self.insert(inf.span, inf.hir_id, Node::Infer(inf));

self.with_parent(inf.hir_id, |this| {
intravisit::walk_inf(this, inf);
});
}

fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));

Expand Down
Loading

0 comments on commit fd853c0

Please sign in to comment.