Skip to content

Commit 44108de

Browse files
committed
use new CastKind instead of lang item
1 parent 7663583 commit 44108de

File tree

23 files changed

+224
-325
lines changed

23 files changed

+224
-325
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,36 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15351535
.unwrap();
15361536
}
15371537
}
1538+
CastKind::ConstToMut => {
1539+
let ty::RawPtr(ty_from, hir::Mutability::Not) =
1540+
op.ty(self.body, tcx).kind()
1541+
else {
1542+
span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
1543+
return;
1544+
};
1545+
let ty::RawPtr(ty_to, hir::Mutability::Mut) = ty.kind() else {
1546+
span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
1547+
return;
1548+
};
1549+
if let Err(terr) = self.eq_types(
1550+
*ty_from,
1551+
*ty_to,
1552+
location.to_locations(),
1553+
ConstraintCategory::Cast {
1554+
is_implicit_coercion: false,
1555+
unsize_to: None,
1556+
},
1557+
) {
1558+
span_mirbug!(
1559+
self,
1560+
rvalue,
1561+
"relating {:?} with {:?} yields {:?}",
1562+
ty_from,
1563+
ty_to,
1564+
terr
1565+
);
1566+
}
1567+
}
15381568
CastKind::Transmute => {
15391569
let ty_from = op.ty(self.body, tcx);
15401570
match ty_from.kind() {

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
740740
| CastKind::IntToFloat
741741
| CastKind::FnPtrToPtr
742742
| CastKind::PtrToPtr
743+
| CastKind::ConstToMut
743744
| CastKind::PointerExposeProvenance
744745
| CastKind::PointerWithExposedProvenance,
745746
ref operand,

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
444444
) => {
445445
bug!("{kind:?} is for borrowck, and should never appear in codegen");
446446
}
447-
mir::CastKind::PtrToPtr
447+
mir::CastKind::PtrToPtr | mir::CastKind::ConstToMut
448448
if bx.cx().is_backend_scalar_pair(operand.layout) =>
449449
{
450450
if let OperandValue::Pair(data_ptr, meta) = operand.val {
@@ -463,6 +463,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
463463
| mir::CastKind::FloatToFloat
464464
| mir::CastKind::IntToFloat
465465
| mir::CastKind::PtrToPtr
466+
| mir::CastKind::ConstToMut
466467
| mir::CastKind::FnPtrToPtr
467468
// Since int2ptr can have arbitrary integer types as input (so we have to do
468469
// sign extension and all that), it is currently best handled in the same code

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
6161
self.write_immediate(*res, dest)?;
6262
}
6363

64-
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
64+
CastKind::FnPtrToPtr | CastKind::PtrToPtr | CastKind::ConstToMut => {
6565
let src = self.read_immediate(src)?;
6666
let res = self.ptr_to_ptr(&src, cast_layout)?;
6767
self.write_immediate(*res, dest)?;

compiler/rustc_hir/src/lang_items.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ language_item_table! {
331331
FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
332332
FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
333333

334-
BoxUninitAsMutPtr, sym::box_uninit_as_mut_ptr, box_uninit_as_mut_ptr_fn, Target::Fn, GenericRequirement::Exact(1);
335334
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
336335
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
337336

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ impl<'tcx> Rvalue<'tcx> {
748748
| CastKind::IntToFloat
749749
| CastKind::FnPtrToPtr
750750
| CastKind::PtrToPtr
751+
| CastKind::ConstToMut
751752
| CastKind::PointerCoercion(_, _)
752753
| CastKind::PointerWithExposedProvenance
753754
| CastKind::Transmute

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,9 @@ pub enum CastKind {
14971497
FloatToFloat,
14981498
IntToFloat,
14991499
PtrToPtr,
1500+
/// `*const T` to `*mut T` that keeps `T` the same. Needed for `vec!` macro lowering
1501+
/// to avoid a lang item doing effectively just that.
1502+
ConstToMut,
15001503
FnPtrToPtr,
15011504
/// Reinterpret the bits of the input as a different type.
15021505
///

compiler/rustc_mir_build/src/builder/expr/into.rs

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! See docs in build/expr/mod.rs
22
3+
use rustc_abi::FieldIdx;
34
use rustc_ast::{AsmMacro, InlineAsmOptions};
45
use rustc_data_structures::fx::FxHashMap;
56
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -398,73 +399,95 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
398399
sym::write_box_via_move => {
399400
// `write_box_via_move(b, val)` becomes
400401
// ```
401-
// *box_uninit_as_mut_ptr(&mut b) = val;
402+
// let _tmp = b.0.pointer.pointer as *mut _;
403+
// *_tmp.value.value = val;
402404
// b
403405
// ```
404-
let tcx = this.tcx;
405-
let t = generic_args.type_at(0);
406406
let [b, val] = **args else {
407407
span_bug!(expr_span, "invalid init_box_via_move call")
408408
};
409-
let box_ty = this.thir.exprs[b].ty;
410409
let Some(b) = unpack!(block = this.as_local_operand(block, b)).place()
411410
else {
412411
span_bug!(expr_span, "invalid init_box_via_move call")
413412
};
414413

415-
// Create reference to `b`.
416-
let box_ref = this
414+
// Projecting to a field requires the type of that field.
415+
// Computing all those types for our 5 projections is quite annoying...
416+
// we are projecting through: `Unique<MaybeUninit<T>>`,
417+
// `NonNull<MaybeUninit<T>>`, `*mut MaybeUninit<T>` `MaybeUninit<T>`,
418+
// `ManuallyDrop<T>`, `T`.
419+
let tcx = this.tcx;
420+
let field_ty = |adt: ty::AdtDef<'tcx>, idx: FieldIdx| {
421+
let field = adt.non_enum_variant().fields[idx].did;
422+
tcx.type_of(field).instantiate_identity()
423+
};
424+
let box_adt =
425+
tcx.adt_def(tcx.require_lang_item(LangItem::OwnedBox, DUMMY_SP));
426+
let unique_adt = field_ty(box_adt, FieldIdx::ZERO).ty_adt_def().unwrap();
427+
let nonnull_adt =
428+
field_ty(unique_adt, FieldIdx::ZERO).ty_adt_def().unwrap();
429+
let manually_drop_adt =
430+
tcx.adt_def(tcx.require_lang_item(LangItem::ManuallyDrop, DUMMY_SP));
431+
432+
let ty = generic_args.type_at(0);
433+
let manually_drop_ty =
434+
Ty::new_adt(tcx, manually_drop_adt, tcx.mk_args(&[ty.into()]));
435+
let maybe_uninit_ty = Ty::new_maybe_uninit(tcx, ty);
436+
let const_ptr_maybe_uninit_ty = Ty::new_imm_ptr(tcx, maybe_uninit_ty);
437+
let mut_ptr_maybe_uninit_ty = Ty::new_mut_ptr(tcx, maybe_uninit_ty);
438+
439+
let maybe_uninit_ty_args = tcx.mk_args(&[maybe_uninit_ty.into()]);
440+
let unique_ty = Ty::new_adt(tcx, unique_adt, maybe_uninit_ty_args);
441+
let nonnull_ty = Ty::new_adt(tcx, nonnull_adt, maybe_uninit_ty_args);
442+
443+
// We need a temporary to store the pointer cast to `*mut`.
444+
let tmp_ptr = this
417445
.local_decls
418-
.push(LocalDecl::new(Ty::new_mut_ptr(tcx, box_ty), expr_span));
446+
.push(LocalDecl::new(mut_ptr_maybe_uninit_ty, expr_span));
419447
this.cfg.push(
420448
block,
421-
Statement::new(source_info, StatementKind::StorageLive(box_ref)),
449+
Statement::new(source_info, StatementKind::StorageLive(tmp_ptr)),
422450
);
423451
// Make sure `StorageDead` gets emitted.
424452
this.schedule_drop_storage_and_value(
425453
expr_span,
426454
this.local_scope(),
427-
box_ref,
455+
tmp_ptr,
428456
);
457+
458+
// Generate `let _tmp = b.0.pointer.pointer as *mut _;` using a
459+
// `ConstToMut` cast so that borrowck makes sure this cast does not change
460+
// lifetimes.
429461
this.cfg.push_assign(
430462
block,
431463
source_info,
432-
box_ref.into(),
433-
Rvalue::RawPtr(RawPtrKind::Mut, b),
464+
tmp_ptr.into(),
465+
Rvalue::Cast(
466+
CastKind::ConstToMut,
467+
Operand::Copy(b.project_deeper(
468+
&[
469+
ProjectionElem::Field(FieldIdx::ZERO, unique_ty),
470+
ProjectionElem::Field(FieldIdx::ZERO, nonnull_ty),
471+
ProjectionElem::Field(
472+
FieldIdx::ZERO,
473+
const_ptr_maybe_uninit_ty,
474+
),
475+
],
476+
tcx,
477+
)),
478+
mut_ptr_maybe_uninit_ty,
479+
),
434480
);
435481

436-
// Invoke `box_uninit_as_mut_ptr`.
437-
let as_mut_ptr_fn = Operand::function_handle(
482+
// Generate `*_tmp.value.value = val;`
483+
let ptr_deref = Place::from(tmp_ptr).project_deeper(
484+
&[
485+
ProjectionElem::Deref,
486+
ProjectionElem::Field(FieldIdx::from_u32(1), manually_drop_ty),
487+
ProjectionElem::Field(FieldIdx::ZERO, ty),
488+
],
438489
tcx,
439-
tcx.require_lang_item(LangItem::BoxUninitAsMutPtr, expr_span),
440-
[t.into()],
441-
expr_span,
442490
);
443-
let inner_ptr = this.temp(Ty::new_mut_ptr(tcx, t), expr_span);
444-
let success = this.cfg.start_new_block();
445-
this.cfg.terminate(
446-
block,
447-
source_info,
448-
TerminatorKind::Call {
449-
func: as_mut_ptr_fn,
450-
args: [Spanned {
451-
node: Operand::Copy(box_ref.into()),
452-
span: expr_span,
453-
}]
454-
.into(),
455-
destination: inner_ptr,
456-
target: Some(success),
457-
unwind: UnwindAction::Unreachable,
458-
call_source: CallSource::Misc,
459-
fn_span: expr_span,
460-
},
461-
);
462-
this.diverge_from(block);
463-
block = success;
464-
465-
// Store `val` into `inner_ptr`.
466-
let ptr_deref = Place::from(inner_ptr)
467-
.project_deeper(&[ProjectionElem::Deref], this.tcx);
468491
unpack!(block = this.expr_into_dest(ptr_deref, block, val));
469492

470493
// Return `b`

compiler/rustc_mir_transform/src/validate.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
13911391
ty::RawPtr(..)
13921392
);
13931393
}
1394+
CastKind::ConstToMut => {
1395+
check_kinds!(
1396+
op_ty,
1397+
"CastKind::{kind:?} input must be a const raw pointer, not {:?}",
1398+
ty::RawPtr(_, Mutability::Not)
1399+
);
1400+
check_kinds!(
1401+
target_type,
1402+
"CastKind::{kind:?} output must be a mut raw pointer, not {:?}",
1403+
ty::RawPtr(_, Mutability::Mut)
1404+
);
1405+
}
13941406
CastKind::FloatToFloat | CastKind::FloatToInt => {
13951407
if !op_ty.is_floating_point() || !target_type.is_numeric() {
13961408
self.fail(

compiler/rustc_public/src/mir/body.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ pub enum CastKind {
10131013
FloatToFloat,
10141014
IntToFloat,
10151015
PtrToPtr,
1016+
ConstToMut,
10161017
FnPtrToPtr,
10171018
Transmute,
10181019
Subtype,

0 commit comments

Comments
 (0)