Skip to content

Commit 2ae0dbc

Browse files
committed
Check for occupied niches
1 parent bbcc169 commit 2ae0dbc

File tree

39 files changed

+727
-49
lines changed

39 files changed

+727
-49
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

+13
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,19 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
368368
source_info.span,
369369
);
370370
}
371+
AssertKind::OccupiedNiche { ref found, ref start, ref end } => {
372+
let found = codegen_operand(fx, found).load_scalar(fx);
373+
let start = codegen_operand(fx, start).load_scalar(fx);
374+
let end = codegen_operand(fx, end).load_scalar(fx);
375+
let location = fx.get_caller_location(source_info).load_scalar(fx);
376+
377+
codegen_panic_inner(
378+
fx,
379+
rustc_hir::LangItem::PanicOccupiedNiche,
380+
&[found, start, end, location],
381+
source_info.span,
382+
)
383+
}
371384
_ => {
372385
let msg_str = msg.description();
373386
codegen_panic(fx, msg_str, source_info);

compiler/rustc_codegen_ssa/src/common.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use rustc_hir::LangItem;
44
use rustc_middle::mir;
5-
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
5+
use rustc_middle::ty::{self, layout::TyAndLayout, GenericArg, Ty, TyCtxt};
66
use rustc_span::Span;
77

88
use crate::base;
@@ -120,10 +120,15 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
120120
bx: &Bx,
121121
span: Option<Span>,
122122
li: LangItem,
123+
generic: Option<GenericArg<'tcx>>,
123124
) -> (Bx::FnAbiOfResult, Bx::Value) {
124125
let tcx = bx.tcx();
125126
let def_id = tcx.require_lang_item(li, span);
126-
let instance = ty::Instance::mono(tcx, def_id);
127+
let instance = if let Some(arg) = generic {
128+
ty::Instance::new(def_id, tcx.mk_args(&[arg]))
129+
} else {
130+
ty::Instance::mono(tcx, def_id)
131+
};
127132
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
128133
}
129134

compiler/rustc_codegen_ssa/src/mir/block.rs

+28-12
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
573573
mergeable_succ: bool,
574574
) -> MergingSucc {
575575
let span = terminator.source_info.span;
576-
let cond = self.codegen_operand(bx, cond).immediate();
576+
let mut cond = self.codegen_operand(bx, cond).immediate();
577577
let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1);
578578

579579
// This case can currently arise only from functions marked
@@ -589,8 +589,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
589589
return helper.funclet_br(self, bx, target, mergeable_succ);
590590
}
591591

592-
// Pass the condition through llvm.expect for branch hinting.
593-
let cond = bx.expect(cond, expected);
592+
if bx.tcx().sess.opts.optimize != OptLevel::No {
593+
// Pass the condition through llvm.expect for branch hinting.
594+
cond = bx.expect(cond, expected);
595+
}
594596

595597
// Create the failure block and the conditional branch to it.
596598
let lltarget = helper.llbb_with_cleanup(self, target);
@@ -609,30 +611,40 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
609611
let location = self.get_caller_location(bx, terminator.source_info).immediate();
610612

611613
// Put together the arguments to the panic entry point.
612-
let (lang_item, args) = match msg {
614+
let (lang_item, args, generic) = match msg {
613615
AssertKind::BoundsCheck { ref len, ref index } => {
614616
let len = self.codegen_operand(bx, len).immediate();
615617
let index = self.codegen_operand(bx, index).immediate();
616618
// It's `fn panic_bounds_check(index: usize, len: usize)`,
617619
// and `#[track_caller]` adds an implicit third argument.
618-
(LangItem::PanicBoundsCheck, vec![index, len, location])
620+
(LangItem::PanicBoundsCheck, vec![index, len, location], None)
619621
}
620622
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
621623
let required = self.codegen_operand(bx, required).immediate();
622624
let found = self.codegen_operand(bx, found).immediate();
623625
// It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`,
624626
// and `#[track_caller]` adds an implicit third argument.
625-
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
627+
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location], None)
628+
}
629+
AssertKind::OccupiedNiche { ref found, ref start, ref end } => {
630+
let found = self.codegen_operand(bx, found);
631+
let generic_arg = ty::GenericArg::from(found.layout.ty);
632+
let found = found.immediate();
633+
let start = self.codegen_operand(bx, start).immediate();
634+
let end = self.codegen_operand(bx, end).immediate();
635+
// It's `fn panic_occupied_niche<T>(found: T, start: T, end: T)`,
636+
// and `#[track_caller]` adds an implicit fourth argument.
637+
(LangItem::PanicOccupiedNiche, vec![found, start, end, location], Some(generic_arg))
626638
}
627639
_ => {
628640
let msg = bx.const_str(msg.description());
629641
// It's `pub fn panic(expr: &str)`, with the wide reference being passed
630642
// as two arguments, and `#[track_caller]` adds an implicit third argument.
631-
(LangItem::Panic, vec![msg.0, msg.1, location])
643+
(LangItem::Panic, vec![msg.0, msg.1, location], None)
632644
}
633645
};
634646

635-
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
647+
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item, generic);
636648

637649
// Codegen the actual panic invoke/call.
638650
let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
@@ -651,7 +663,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
651663
self.set_debug_loc(bx, terminator.source_info);
652664

653665
// Obtain the panic entry point.
654-
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item());
666+
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item(), None);
655667

656668
// Codegen the actual panic invoke/call.
657669
let merging_succ = helper.do_call(
@@ -712,8 +724,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
712724
let msg = bx.const_str(&msg_str);
713725

714726
// Obtain the panic entry point.
715-
let (fn_abi, llfn) =
716-
common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
727+
let (fn_abi, llfn) = common::build_langcall(
728+
bx,
729+
Some(source_info.span),
730+
LangItem::PanicNounwind,
731+
None,
732+
);
717733

718734
// Codegen the actual panic invoke/call.
719735
helper.do_call(
@@ -1622,7 +1638,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16221638

16231639
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
16241640

1625-
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
1641+
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item(), None);
16261642
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
16271643

16281644
let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());

compiler/rustc_const_eval/src/const_eval/machine.rs

+5
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
542542
found: eval_to_int(found)?,
543543
}
544544
}
545+
OccupiedNiche { ref found, ref start, ref end } => OccupiedNiche {
546+
found: eval_to_int(found)?,
547+
start: eval_to_int(start)?,
548+
end: eval_to_int(end)?,
549+
},
545550
};
546551
Err(ConstEvalErrKind::AssertFailure(err).into())
547552
}

compiler/rustc_const_eval/src/interpret/cast.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
66
use rustc_middle::mir::CastKind;
77
use rustc_middle::ty::adjustment::PointerCoercion;
88
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
9+
use rustc_middle::ty::print::with_no_trimmed_paths;
910
use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
1011
use rustc_target::abi::Integer;
1112
use rustc_type_ir::TyKind::*;
@@ -147,8 +148,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
147148
if src.layout.size != dest.layout.size {
148149
let src_bytes = src.layout.size.bytes();
149150
let dest_bytes = dest.layout.size.bytes();
150-
let src_ty = format!("{}", src.layout.ty);
151-
let dest_ty = format!("{}", dest.layout.ty);
151+
let src_ty = with_no_trimmed_paths!(format!("{}", src.layout.ty));
152+
let dest_ty = with_no_trimmed_paths!(format!("{}", dest.layout.ty));
152153
throw_ub_custom!(
153154
fluent::const_eval_invalid_transmute,
154155
src_bytes = src_bytes,

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ language_item_table! {
234234
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
235235
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
236236
PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);
237+
PanicOccupiedNiche, sym::panic_occupied_niche, panic_occupied_niche_fn, Target::Fn, GenericRequirement::Exact(1);
237238
PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
238239
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
239240
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;

compiler/rustc_middle/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ middle_assert_divide_by_zero =
1515
middle_assert_misaligned_ptr_deref =
1616
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
1717
18+
middle_assert_occupied_niche =
19+
occupied niche: {$found} must be in {$start}..={$end}
20+
1821
middle_assert_op_overflow =
1922
attempt to compute `{$left} {$op} {$right}`, which would overflow
2023

compiler/rustc_middle/src/mir/syntax.rs

+1
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ pub enum AssertKind<O> {
886886
ResumedAfterReturn(CoroutineKind),
887887
ResumedAfterPanic(CoroutineKind),
888888
MisalignedPointerDereference { required: O, found: O },
889+
OccupiedNiche { found: O, start: O, end: O },
889890
}
890891

891892
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]

compiler/rustc_middle/src/mir/terminator.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<O> AssertKind<O> {
157157
"`gen fn` should just keep returning `None` after panicking"
158158
}
159159

160-
BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
160+
BoundsCheck { .. } | MisalignedPointerDereference { .. } | OccupiedNiche { .. } => {
161161
bug!("Unexpected AssertKind")
162162
}
163163
}
@@ -220,6 +220,13 @@ impl<O> AssertKind<O> {
220220
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
221221
)
222222
}
223+
OccupiedNiche { found, start, end } => {
224+
write!(
225+
f,
226+
"\"occupied niche: {{}} must be in {{}}..={{}}\", {:?}, {:?}, {:?}",
227+
found, start, end
228+
)
229+
}
223230
_ => write!(f, "\"{}\"", self.description()),
224231
}
225232
}
@@ -255,8 +262,8 @@ impl<O> AssertKind<O> {
255262
ResumedAfterPanic(CoroutineKind::Coroutine) => {
256263
middle_assert_coroutine_resume_after_panic
257264
}
258-
259265
MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
266+
OccupiedNiche { .. } => middle_assert_occupied_niche,
260267
}
261268
}
262269

@@ -293,6 +300,11 @@ impl<O> AssertKind<O> {
293300
add!("required", format!("{required:#?}"));
294301
add!("found", format!("{found:#?}"));
295302
}
303+
OccupiedNiche { found, start, end } => {
304+
add!("found", format!("{found:?}"));
305+
add!("start", format!("{start:?}"));
306+
add!("end", format!("{end:?}"));
307+
}
296308
}
297309
}
298310
}

compiler/rustc_middle/src/mir/visit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,11 @@ macro_rules! make_mir_visitor {
625625
self.visit_operand(required, location);
626626
self.visit_operand(found, location);
627627
}
628+
OccupiedNiche { found, start, end } => {
629+
self.visit_operand(found, location);
630+
self.visit_operand(start, location);
631+
self.visit_operand(end, location);
632+
}
628633
}
629634
}
630635

0 commit comments

Comments
 (0)