Skip to content
Draft
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}

fn visit_const_arg_expr_field(&mut self, field: &'hir ConstArgExprField<'hir>) {
self.insert(field.span, field.hir_id, Node::ConstArgExprField(field));
self.with_parent(field.hir_id, |this| {
intravisit::walk_const_arg_expr_field(this, field);
})
}

fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt));

Expand Down
31 changes: 31 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2394,6 +2394,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) }
}
ExprKind::Struct(se) => {
let path = self.lower_qpath(
expr.id,
&se.qself,
&se.path,
ParamMode::Explicit,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

let fields = self.arena.alloc_from_iter(se.fields.iter().map(|f| {
let hir_id = self.lower_node_id(f.id);
self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField);

let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind {
self.lower_anon_const_to_const_arg_direct(anon_const)
} else {
self.lower_expr_to_const_arg_direct(&f.expr)
};

&*self.arena.alloc(hir::ConstArgExprField {
hir_id,
field: self.lower_ident(f.ident),
expr: self.arena.alloc(expr),
span: self.lower_span(f.span),
})
}));

ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Struct(path, fields) }
}
ExprKind::Underscore => ConstArg {
hir_id: self.lower_node_id(expr.id),
kind: hir::ConstArgKind::Infer(expr.span, ()),
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use cranelift_codegen::ir::immediates::Offset32;
use rustc_abi::Endian;
use rustc_middle::ty::SimdAlign;
use rustc_middle::ty::{SimdAlign, ValTreeKindExt};

use super::*;
use crate::prelude::*;
Expand Down Expand Up @@ -143,7 +143,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(

let total_len = lane_count * 2;

let indexes = idx.iter().map(|idx| idx.unwrap_leaf().to_u32()).collect::<Vec<u32>>();
let indexes = idx
.iter()
.map(|idx| idx.to_value().valtree.unwrap_leaf().to_u32())
.collect::<Vec<u32>>();

for &idx in &indexes {
assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
Expand Down Expand Up @@ -962,6 +965,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let ptr_val = ptr.load_scalar(fx);

let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment();

Expand Down Expand Up @@ -1007,6 +1012,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let ret_lane_layout = fx.layout_of(ret_lane_ty);

let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment();

Expand Down Expand Up @@ -1060,6 +1067,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let ptr_val = ptr.load_scalar(fx);

let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment();

Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use rustc_hir::{self as hir};
use rustc_middle::mir::BinOp;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::offload_meta::OffloadMetadata;
use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv};
use rustc_middle::ty::{
self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv, ValTreeKindExt,
};
use rustc_middle::{bug, span_bug};
use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol, sym};
Expand Down Expand Up @@ -1547,7 +1549,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
.iter()
.enumerate()
.map(|(arg_idx, val)| {
let idx = val.unwrap_leaf().to_i32();
let idx = val.to_value().valtree.unwrap_leaf().to_i32();
if idx >= i32::try_from(total_len).unwrap() {
bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
span,
Expand Down Expand Up @@ -1944,6 +1946,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// The memory addresses corresponding to the “off” lanes are not accessed.

let alignment = fn_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment();

Expand Down Expand Up @@ -2039,6 +2043,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// The memory addresses corresponding to the “off” lanes are not accessed.

let alignment = fn_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment();

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/mir/constant.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_abi::BackendRepr;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv};
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::{self, Ty, ValTreeKindExt};
use rustc_middle::{bug, mir, span_bug};

use super::FunctionCx;
Expand Down Expand Up @@ -79,12 +79,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// A SIMD type has a single field, which is an array.
let fields = val.unwrap_branch();
assert_eq!(fields.len(), 1);
let array = fields[0].unwrap_branch();
let array = fields[0].to_value().valtree.unwrap_branch();
// Iterate over the array elements to obtain the values in the vector.
let values: Vec<_> = array
.iter()
.map(|field| {
if let Some(prim) = field.try_to_scalar() {
if let Some(prim) = field.to_value().valtree.try_to_scalar() {
let layout = bx.layout_of(field_ty);
let BackendRepr::Scalar(scalar) = layout.backend_repr else {
bug!("from_const: invalid ByVal layout: {:#?}", layout);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_abi::WrappingRange;
use rustc_middle::mir::SourceInfo;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt, ValTreeKindExt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::sym;
Expand Down Expand Up @@ -102,7 +102,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};

let parse_atomic_ordering = |ord: ty::Value<'tcx>| {
let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
let discr = ord.valtree.unwrap_branch()[0].to_value().valtree.unwrap_leaf();
discr.to_atomic_ordering()
};

Expand Down
21 changes: 13 additions & 8 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::layout::{LayoutCx, TyAndLayout};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt, ValTreeKindExt};
use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace};
Expand Down Expand Up @@ -36,13 +36,17 @@ fn branches<'tcx>(
// For enums, we prepend their variant index before the variant's fields so we can figure out
// the variant again when just seeing a valtree.
if let Some(variant) = variant {
branches.push(ty::ValTree::from_scalar_int(*ecx.tcx, variant.as_u32().into()));
branches.push(ty::Const::new_value(
*ecx.tcx,
ty::ValTree::from_scalar_int(*ecx.tcx, variant.as_u32().into()),
ecx.tcx.types.u32,
));
}

for i in 0..field_count {
let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap();
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
branches.push(valtree);
branches.push(ty::Const::new_value(*ecx.tcx, valtree, field.layout.ty));
}

// Have to account for ZSTs here
Expand All @@ -65,7 +69,7 @@ fn slice_branches<'tcx>(
for i in 0..n {
let place_elem = ecx.project_index(place, i).unwrap();
let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?;
elems.push(valtree);
elems.push(ty::Const::new_value(*ecx.tcx, valtree, place_elem.layout.ty));
}

Ok(ty::ValTree::from_branches(*ecx.tcx, elems))
Expand Down Expand Up @@ -201,7 +205,7 @@ fn reconstruct_place_meta<'tcx>(
|ty| ty,
|| {
let branches = last_valtree.unwrap_branch();
last_valtree = *branches.last().unwrap();
last_valtree = branches.last().unwrap().to_value().valtree;
debug!(?branches, ?last_valtree);
},
);
Expand Down Expand Up @@ -306,7 +310,8 @@ pub fn valtree_to_const_value<'tcx>(
for (i, &inner_valtree) in branches.iter().enumerate() {
let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
if !field.is_zst() {
let cv = ty::Value { valtree: inner_valtree, ty: field.ty };
let cv =
ty::Value { valtree: inner_valtree.to_value().valtree, ty: field.ty };
return valtree_to_const_value(tcx, typing_env, cv);
}
}
Expand Down Expand Up @@ -397,7 +402,7 @@ fn valtree_into_mplace<'tcx>(
let (place_adjusted, branches, variant_idx) = match ty.kind() {
ty::Adt(def, _) if def.is_enum() => {
// First element of valtree corresponds to variant
let scalar_int = branches[0].unwrap_leaf();
let scalar_int = branches[0].to_value().valtree.unwrap_leaf();
let variant_idx = VariantIdx::from_u32(scalar_int.to_u32());
let variant = def.variant(variant_idx);
debug!(?variant);
Expand Down Expand Up @@ -425,7 +430,7 @@ fn valtree_into_mplace<'tcx>(
};

debug!(?place_inner);
valtree_into_mplace(ecx, &place_inner, *inner_valtree);
valtree_into_mplace(ecx, &place_inner, inner_valtree.to_value().valtree);
dump_place(ecx, &place_inner);
}

Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_abi::{BackendRepr, Endian};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::{Float, Round};
use rustc_middle::mir::interpret::{InterpErrorKind, Pointer, UndefinedBehaviorInfo};
use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign};
use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign, ValTreeKindExt};
use rustc_middle::{bug, err_ub_format, mir, span_bug, throw_unsup_format, ty};
use rustc_span::{Symbol, sym};
use tracing::trace;
Expand Down Expand Up @@ -552,8 +552,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
assert_eq!(u64::try_from(index_len).unwrap(), dest_len);

for i in 0..dest_len {
let src_index: u64 =
index[usize::try_from(i).unwrap()].unwrap_leaf().to_u32().into();
let src_index: u64 = index[usize::try_from(i).unwrap()]
.to_value()
.valtree
.unwrap_leaf()
.to_u32()
.into();
let dest = self.project_index(&dest, i)?;

let val = if src_index < left_len {
Expand Down Expand Up @@ -658,6 +662,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ptr,
dest_layout,
generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment(),
)?;
Expand Down Expand Up @@ -690,6 +696,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ptr,
args[2].layout,
generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.to_value()
.valtree
.unwrap_leaf()
.to_simd_alignment(),
)?;
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {

pub fn span(&self) -> Span {
match self.kind {
ConstArgKind::Struct(path, _) => path.span(),
ConstArgKind::Path(path) => path.span(),
ConstArgKind::Anon(anon) => anon.span,
ConstArgKind::Error(span, _) => span,
Expand All @@ -513,13 +514,23 @@ pub enum ConstArgKind<'hir, Unambig = ()> {
/// However, in the future, we'll be using it for all of those.
Path(QPath<'hir>),
Anon(&'hir AnonConst),
/// Represents construction of struct/struct variants
Struct(QPath<'hir>, &'hir [&'hir ConstArgExprField<'hir>]),
/// Error const
Error(Span, ErrorGuaranteed),
/// This variant is not always used to represent inference consts, sometimes
/// [`GenericArg::Infer`] is used instead.
Infer(Span, Unambig),
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArgExprField<'hir> {
pub hir_id: HirId,
pub span: Span,
pub field: Ident,
pub expr: &'hir ConstArg<'hir>,
}

#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct InferArg {
#[stable_hasher(ignore)]
Expand Down Expand Up @@ -4711,6 +4722,7 @@ pub enum Node<'hir> {
ConstArg(&'hir ConstArg<'hir>),
Expr(&'hir Expr<'hir>),
ExprField(&'hir ExprField<'hir>),
ConstArgExprField(&'hir ConstArgExprField<'hir>),
Stmt(&'hir Stmt<'hir>),
PathSegment(&'hir PathSegment<'hir>),
Ty(&'hir Ty<'hir>),
Expand Down Expand Up @@ -4770,6 +4782,7 @@ impl<'hir> Node<'hir> {
Node::AssocItemConstraint(c) => Some(c.ident),
Node::PatField(f) => Some(f.ident),
Node::ExprField(f) => Some(f.ident),
Node::ConstArgExprField(f) => Some(f.field),
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
Node::Param(..)
| Node::AnonConst(..)
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ pub trait Visitor<'v>: Sized {
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
walk_expr_field(self, field)
}
fn visit_const_arg_expr_field(&mut self, field: &'v ConstArgExprField<'v>) -> Self::Result {
walk_const_arg_expr_field(self, field)
}
fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
walk_ty_pat(self, p)
}
Expand Down Expand Up @@ -954,6 +957,17 @@ pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField
try_visit!(visitor.visit_ident(*ident));
visitor.visit_expr(*expr)
}

pub fn walk_const_arg_expr_field<'v, V: Visitor<'v>>(
visitor: &mut V,
field: &'v ConstArgExprField<'v>,
) -> V::Result {
let ConstArgExprField { hir_id, field, expr, span: _ } = field;
try_visit!(visitor.visit_id(*hir_id));
try_visit!(visitor.visit_ident(*field));
visitor.visit_const_arg_unambig(*expr)
}

/// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that
/// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited
pub enum InferKind<'hir> {
Expand Down Expand Up @@ -1067,7 +1081,17 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
) -> V::Result {
let ConstArg { hir_id, kind } = const_arg;
try_visit!(visitor.visit_id(*hir_id));

match kind {
ConstArgKind::Struct(qpath, field_exprs) => {
try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span()));

for field_expr in *field_exprs {
try_visit!(visitor.visit_const_arg_expr_field(field_expr));
}

V::Result::output()
}
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
ConstArgKind::Error(_, _) => V::Result::output(), // errors and spans are not important
Expand Down
Loading
Loading