Skip to content
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
41 changes: 41 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,47 @@ 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,
// FIXME(mgca): we may want this to be `Optional` instead, but
// we would also need to make sure that HIR ty lowering errors
// when these paths wind up in signatures.
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);
// FIXME(mgca): This might result in lowering attributes that
// then go unused as the `Target::ExprField` is not actually
// corresponding to `Node::ExprField`.
self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField);

let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind {
let def_id = self.local_def_id(anon_const.id);
let def_kind = self.tcx.def_kind(def_id);
assert_eq!(DefKind::AnonConst, def_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
19 changes: 8 additions & 11 deletions compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
return;
}

let idx = generic_args[2].expect_const().to_value().valtree.unwrap_branch();
let idx = generic_args[2].expect_const().to_branch();

assert_eq!(x.layout(), y.layout());
let layout = x.layout();
Expand All @@ -143,7 +143,7 @@ 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_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 @@ -961,9 +961,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
let ptr_val = ptr.load_scalar(fx);

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

let memflags = match alignment {
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
Expand Down Expand Up @@ -1006,9 +1005,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
let ret_lane_layout = fx.layout_of(ret_lane_ty);

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

let memflags = match alignment {
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
Expand Down Expand Up @@ -1059,9 +1057,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let ret_lane_layout = fx.layout_of(ret_lane_ty);
let ptr_val = ptr.load_scalar(fx);

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

let memflags = match alignment {
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
_ => bug!(),
};
let ptr = args[0].immediate();
let locality = fn_args.const_at(1).to_value().valtree.unwrap_leaf().to_i32();
let locality = fn_args.const_at(1).to_leaf().to_i32();
self.call_intrinsic(
"llvm.prefetch",
&[self.val_ty(ptr)],
Expand Down Expand Up @@ -1536,7 +1536,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
}

if name == sym::simd_shuffle_const_generic {
let idx = fn_args[2].expect_const().to_value().valtree.unwrap_branch();
let idx = fn_args[2].expect_const().to_branch();
let n = idx.len() as u64;

let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
Expand All @@ -1555,7 +1555,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
.iter()
.enumerate()
.map(|(arg_idx, val)| {
let idx = val.unwrap_leaf().to_i32();
let idx = val.to_leaf().to_i32();
if idx >= i32::try_from(total_len).unwrap() {
bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
span,
Expand Down Expand Up @@ -1967,9 +1967,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// those lanes whose `mask` bit is enabled.
// The memory addresses corresponding to the “off” lanes are not accessed.

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

// The element type of the "mask" argument must be a signed integer type of any width
let mask_ty = in_ty;
Expand Down Expand Up @@ -2062,9 +2060,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// those lanes whose `mask` bit is enabled.
// The memory addresses corresponding to the “off” lanes are not accessed.

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

// The element type of the "mask" argument must be a signed integer type of any width
let mask_ty = in_ty;
Expand Down
19 changes: 9 additions & 10 deletions compiler/rustc_codegen_ssa/src/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.flatten()
.map(|val| {
// A SIMD type has a single field, which is an array.
let fields = val.unwrap_branch();
let fields = val.to_branch();
assert_eq!(fields.len(), 1);
let array = fields[0].unwrap_branch();
let array = fields[0].to_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() {
let layout = bx.layout_of(field_ty);
let BackendRepr::Scalar(scalar) = layout.backend_repr else {
bug!("from_const: invalid ByVal layout: {:#?}", layout);
};
bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
} else {
let Some(prim) = field.try_to_scalar() else {
bug!("field is not a scalar {:?}", field)
}
};
let layout = bx.layout_of(field_ty);
let BackendRepr::Scalar(scalar) = layout.backend_repr else {
bug!("from_const: invalid ByVal layout: {:#?}", layout);
};
bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
})
.collect();
bx.const_vector(&values)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
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.to_branch()[0].to_leaf();
discr.to_atomic_ordering()
};

Expand Down
31 changes: 18 additions & 13 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
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 @@ -200,8 +204,8 @@ fn reconstruct_place_meta<'tcx>(
&ObligationCause::dummy(),
|ty| ty,
|| {
let branches = last_valtree.unwrap_branch();
last_valtree = *branches.last().unwrap();
let branches = last_valtree.to_branch();
last_valtree = branches.last().unwrap().to_value().valtree;
debug!(?branches, ?last_valtree);
},
);
Expand All @@ -212,7 +216,7 @@ fn reconstruct_place_meta<'tcx>(
};

// Get the number of elements in the unsized field.
let num_elems = last_valtree.unwrap_branch().len();
let num_elems = last_valtree.to_branch().len();
MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx))
}

Expand Down Expand Up @@ -274,7 +278,7 @@ pub fn valtree_to_const_value<'tcx>(
mir::ConstValue::ZeroSized
}
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_, _) => {
mir::ConstValue::Scalar(Scalar::Int(cv.valtree.unwrap_leaf()))
mir::ConstValue::Scalar(Scalar::Int(cv.to_leaf()))
}
ty::Pat(ty, _) => {
let cv = ty::Value { valtree: cv.valtree, ty };
Expand All @@ -301,12 +305,13 @@ pub fn valtree_to_const_value<'tcx>(
|| matches!(cv.ty.kind(), ty::Adt(def, _) if def.is_struct()))
{
// A Scalar tuple/struct; we can avoid creating an allocation.
let branches = cv.valtree.unwrap_branch();
let branches = cv.to_branch();
// Find the non-ZST field. (There can be aligned ZST!)
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 @@ -381,7 +386,7 @@ fn valtree_into_mplace<'tcx>(
// Zero-sized type, nothing to do.
}
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(..) => {
let scalar_int = valtree.unwrap_leaf();
let scalar_int = valtree.to_leaf();
debug!("writing trivial valtree {:?} to place {:?}", scalar_int, place);
ecx.write_immediate(Immediate::Scalar(scalar_int.into()), place).unwrap();
}
Expand All @@ -391,13 +396,13 @@ fn valtree_into_mplace<'tcx>(
ecx.write_immediate(imm, place).unwrap();
}
ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str | ty::Slice(_) => {
let branches = valtree.unwrap_branch();
let branches = valtree.to_branch();

// Need to downcast place for enums
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_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
12 changes: 4 additions & 8 deletions compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,15 +545,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (right, right_len) = self.project_to_simd(&args[1])?;
let (dest, dest_len) = self.project_to_simd(&dest)?;

let index = generic_args[2].expect_const().to_value().valtree.unwrap_branch();
let index = generic_args[2].expect_const().to_branch();
let index_len = index.len();

assert_eq!(left_len, right_len);
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();
index[usize::try_from(i).unwrap()].to_leaf().to_u32().into();
let dest = self.project_index(&dest, i)?;

let val = if src_index < left_len {
Expand Down Expand Up @@ -657,9 +657,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.check_simd_ptr_alignment(
ptr,
dest_layout,
generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.unwrap_leaf()
.to_simd_alignment(),
generic_args[3].expect_const().to_branch()[0].to_leaf().to_simd_alignment(),
)?;

for i in 0..dest_len {
Expand Down Expand Up @@ -689,9 +687,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.check_simd_ptr_alignment(
ptr,
args[2].layout,
generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
.unwrap_leaf()
.to_simd_alignment(),
generic_args[3].expect_const().to_branch()[0].to_leaf().to_simd_alignment(),
)?;

for i in 0..vals_len {
Expand Down
Loading
Loading