Skip to content

[WIP] Make less anon consts/Do a little min_generic_const_exprs #111111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1162,7 +1162,7 @@ impl Expr {
/// `min_const_generics` as more complex expressions are not supported.
///
/// Does not ensure that the path resolves to a const param, the caller should check this.
pub fn is_potential_trivial_const_arg(&self) -> bool {
pub fn is_potential_trivial_const_arg(&self) -> Option<(NodeId, &Path)> {
let this = if let ExprKind::Block(block, None) = &self.kind
&& block.stmts.len() == 1
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
@@ -1175,9 +1175,9 @@ impl Expr {
if let ExprKind::Path(None, path) = &this.kind
&& path.is_potential_trivial_const_arg()
{
true
Some((this.id, path))
} else {
false
None
}
}

5 changes: 4 additions & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -77,7 +77,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ExprKind::Repeat(expr, count) => {
let expr = self.lower_expr(expr);
let count = self.lower_array_length(count);
let count = self.lower_array_length(
count,
&ImplTraitContext::Disallowed(ImplTraitPosition::RepeatExprs),
);
hir::ExprKind::Repeat(expr, count)
}
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
@@ -168,7 +168,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
intravisit::walk_generic_param(self, param);
}

fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) {
self.with_parent(param, |this| {
intravisit::walk_const_param_default(this, ct);
})
95 changes: 57 additions & 38 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -257,6 +257,7 @@ enum ImplTraitContext {
/// Position in which `impl Trait` is disallowed.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ImplTraitPosition {
RepeatExprs,
Path,
Variable,
Trait,
@@ -288,6 +289,7 @@ enum ImplTraitPosition {
impl std::fmt::Display for ImplTraitPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match self {
ImplTraitPosition::RepeatExprs => "repeat expr lengths",
ImplTraitPosition::Path => "paths",
ImplTraitPosition::Variable => "variable bindings",
ImplTraitPosition::Trait => "traits",
@@ -1204,48 +1206,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ty,
);

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

let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id();
let span = self.lower_span(ty.span);

// Add a definition for the in-band const def.
let def_id = self.create_def(
parent_def_id.def_id,
node_id,
DefPathData::AnonConst,
span,
return GenericArg::Const(
self.lower_const_arg_param(ty.id, path, itctx),
);

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

let ct = self.with_new_scopes(|this| hir::AnonConst {
def_id,
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 });
}
}
}
_ => {}
}
GenericArg::Type(self.lower_ty(&ty, itctx))
}
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
value: self.lower_anon_const(&ct),
span: self.lower_span(ct.value.span),
ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_const_arg(ct, itctx)),
}
}

#[instrument(level = "debug", skip(self), ret)]
fn lower_const_arg(
&mut self,
c: &AnonConst,
itctx: &ImplTraitContext,
) -> &'hir hir::ConstArg<'hir> {
match c.value.is_potential_trivial_const_arg() {
Some((path_id, param_path)) => self.lower_const_arg_param(path_id, param_path, itctx),
None => self.arena.alloc(ConstArg {
kind: hir::ConstArgKind::AnonConst(
self.lower_span(c.value.span),
self.lower_anon_const(c),
),
}),
}
}

fn lower_const_arg_param(
&mut self,
path_id: NodeId,
param_path: &Path,
itctx: &ImplTraitContext,
) -> &'hir hir::ConstArg<'hir> {
self.arena.alloc(ConstArg {
kind: hir::ConstArgKind::Param(
self.lower_node_id(path_id),
self.lower_qpath(path_id, &None, param_path, ParamMode::ExplicitNamed, itctx),
),
})
}

#[instrument(level = "debug", skip(self))]
fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> {
self.arena.alloc(self.lower_ty_direct(t, itctx))
@@ -1360,7 +1365,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
))
}
TyKind::Array(ty, length) => {
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length, itctx))
}
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
TyKind::TraitObject(bounds, kind) => {
@@ -2282,7 +2287,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
);
let default = default.as_ref().map(|def| self.lower_anon_const(def));
let default = default.as_ref().map(|def| {
self.lower_const_arg(
def,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
)
});
(
hir::ParamName::Plain(self.lower_ident(param.ident)),
hir::GenericParamKind::Const { ty, default },
@@ -2389,11 +2399,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.expr_block(block)
}

fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
match c.value.kind {
fn lower_array_length(
&mut self,
c: &AnonConst,
itctx: &ImplTraitContext,
) -> &'hir hir::ConstArg<'hir> {
let const_arg = match c.value.kind {
ExprKind::Underscore => {
if self.tcx.features().generic_arg_infer {
hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span)
hir::ConstArg {
kind: hir::ConstArgKind::Infer(self.lower_node_id(c.id), c.value.span),
}
} else {
feature_err(
&self.tcx.sess.parse_sess,
@@ -2402,11 +2418,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
"using `_` for array lengths is unstable",
)
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
hir::ArrayLen::Body(self.lower_anon_const(c))
hir::ConstArg {
kind: hir::ConstArgKind::AnonConst(c.value.span, self.lower_anon_const(c)),
}
}
}
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
}
_ => return self.lower_const_arg(c, itctx),
};
self.arena.alloc(const_arg)
}

fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use std::borrow::Cow;

use either::{Left, Right};

use rustc_hir::def::DefKind;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::pretty::display_allocation;
@@ -44,6 +44,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::AssocConst
| DefKind::Ctor(_, CtorKind::Const)
),
"Unexpected DefKind: {:?}",
ecx.tcx.def_kind(cid.instance.def_id())
63 changes: 38 additions & 25 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -242,9 +242,33 @@ impl<'hir> PathSegment<'hir> {
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArg {
pub value: AnonConst,
pub span: Span,
pub struct ConstArg<'hir> {
pub kind: ConstArgKind<'hir>,
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub enum ConstArgKind<'hir> {
AnonConst(Span, AnonConst),
Param(HirId, QPath<'hir>),
Infer(HirId, Span),
}

impl<'hir> ConstArg<'hir> {
pub fn span(&self) -> Span {
match self.kind {
ConstArgKind::AnonConst(span, _) => span,
ConstArgKind::Param(_, qpath) => qpath.span(),
ConstArgKind::Infer(_, span) => span,
}
}

pub fn hir_id(&self) -> HirId {
match self.kind {
ConstArgKind::AnonConst(_, ct) => ct.hir_id,
ConstArgKind::Param(id, _) => id,
ConstArgKind::Infer(id, _) => id,
}
}
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
@@ -263,7 +287,7 @@ impl InferArg {
pub enum GenericArg<'hir> {
Lifetime(&'hir Lifetime),
Type(&'hir Ty<'hir>),
Const(ConstArg),
Const(&'hir ConstArg<'hir>),
Infer(InferArg),
}

@@ -272,7 +296,7 @@ impl GenericArg<'_> {
match self {
GenericArg::Lifetime(l) => l.ident.span,
GenericArg::Type(t) => t.span,
GenericArg::Const(c) => c.span,
GenericArg::Const(c) => c.span(),
GenericArg::Infer(i) => i.span,
}
}
@@ -281,7 +305,7 @@ impl GenericArg<'_> {
match self {
GenericArg::Lifetime(l) => l.hir_id,
GenericArg::Type(t) => t.hir_id,
GenericArg::Const(c) => c.value.hir_id,
GenericArg::Const(c) => c.hir_id(),
GenericArg::Infer(i) => i.hir_id,
}
}
@@ -498,7 +522,7 @@ pub enum GenericParamKind<'hir> {
Const {
ty: &'hir Ty<'hir>,
/// Optional default value for the const generic param
default: Option<AnonConst>,
default: Option<&'hir ConstArg<'hir>>,
},
}

@@ -1646,20 +1670,6 @@ impl fmt::Display for ConstContext {
/// A literal.
pub type Lit = Spanned<LitKind>;

#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum ArrayLen {
Infer(HirId, Span),
Body(AnonConst),
}

impl ArrayLen {
pub fn hir_id(&self) -> HirId {
match self {
&ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, .. }) => hir_id,
}
}
}

/// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g., array lengths)
@@ -2034,7 +2044,7 @@ pub enum ExprKind<'hir> {
///
/// E.g., `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it.
Repeat(&'hir Expr<'hir>, ArrayLen),
Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>),

/// A suspension point for generators (i.e., `yield <expr>`).
Yield(&'hir Expr<'hir>, YieldSource),
@@ -2671,7 +2681,7 @@ pub enum TyKind<'hir> {
/// A variable length slice (i.e., `[T]`).
Slice(&'hir Ty<'hir>),
/// A fixed length array (i.e., `[T; n]`).
Array(&'hir Ty<'hir>, ArrayLen),
Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>),
/// A raw pointer (i.e., `*const T` or `*mut T`).
Ptr(MutTy<'hir>),
/// A reference (i.e., `&'a T` or `&'a mut T`).
@@ -3757,7 +3767,10 @@ impl<'hir> Node<'hir> {
kind:
ExprKind::ConstBlock(AnonConst { body, .. })
| ExprKind::Closure(Closure { body, .. })
| ExprKind::Repeat(_, ArrayLen::Body(AnonConst { body, .. })),
| ExprKind::Repeat(
_,
ConstArg { kind: ConstArgKind::AnonConst(_, AnonConst { body, .. }) },
),
..
}) => Some(*body),
_ => None,
@@ -4011,7 +4024,7 @@ mod size_asserts {
static_assert_size!(FnDecl<'_>, 40);
static_assert_size!(ForeignItem<'_>, 72);
static_assert_size!(ForeignItemKind<'_>, 40);
static_assert_size!(GenericArg<'_>, 32);
static_assert_size!(GenericArg<'_>, 16);
static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 80);
Loading