Auto merge of #121662 - saethlin:precondition-unification, r= · rust-lang/rust@c492ab1 (original) (raw)
46 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2001,7 +2001,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | ||
2001 | 2001 | ConstraintCategory::SizedBound, |
2002 | 2002 | ); |
2003 | 2003 | } |
2004 | -&Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {} | |
2004 | +&Rvalue::NullaryOp(NullOp::UbCheck(_), _) => {} | |
2005 | 2005 | |
2006 | 2006 | Rvalue::ShallowInitBox(operand, ty) => { |
2007 | 2007 | self.check_operand(operand, location); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -767,7 +767,7 @@ fn codegen_stmt<'tcx>( | ||
767 | 767 | NullOp::OffsetOf(fields) => { |
768 | 768 | layout.offset_of_subfield(fx, fields.iter()).bytes() |
769 | 769 | } |
770 | -NullOp::DebugAssertions => { | |
770 | +NullOp::UbCheck(_) => { | |
771 | 771 | let val = fx.tcx.sess.opts.debug_assertions; |
772 | 772 | let val = CValue::by_val( |
773 | 773 | fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -684,7 +684,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | ||
684 | 684 | let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes(); |
685 | 685 | bx.cx().const_usize(val) |
686 | 686 | } |
687 | - mir::NullOp::DebugAssertions => { | |
687 | + mir::NullOp::UbCheck(_) => { | |
688 | +// In codegen, we want to check for language UB and library UB | |
688 | 689 | let val = bx.tcx().sess.opts.debug_assertions; |
689 | 690 | bx.cx().const_bool(val) |
690 | 691 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -258,10 +258,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ||
258 | 258 | let val = layout.offset_of_subfield(self, fields.iter()).bytes(); |
259 | 259 | Scalar::from_target_usize(val, self) |
260 | 260 | } |
261 | - mir::NullOp::DebugAssertions => { | |
262 | -// The checks hidden behind this are always better done by the interpreter | |
263 | -// itself, because it knows the runtime state better. | |
264 | -Scalar::from_bool(false) | |
261 | + mir::NullOp::UbCheck(kind) => { | |
262 | +// We want to enable checks for library UB, because the interpreter doesn't | |
263 | +// know about those on its own. | |
264 | +// But we want to disable checks for language UB, because the interpreter | |
265 | +// has its own better checks for that. | |
266 | +let should_check = match kind { | |
267 | + mir::UbKind::LibraryUb => true, | |
268 | + mir::UbKind::LanguageUb => false, | |
269 | +}; | |
270 | +Scalar::from_bool(should_check) | |
265 | 271 | } |
266 | 272 | }; |
267 | 273 | self.write_scalar(val, &dest)?; |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -558,7 +558,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | ||||
558 | 558 | Rvalue::Cast(_, _, _) => {} | ||
559 | 559 | |||
560 | 560 | Rvalue::NullaryOp( | ||
561 | -NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, | |
561 | +NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbCheck(_), | |
562 | 562 | _, | ||
563 | 563 | ) => {} | ||
564 | 564 | Rvalue::ShallowInitBox(_, _) => {} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1157,7 +1157,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | ||||
1157 | 1157 | Rvalue::Repeat(_, _) | ||
1158 | 1158 | | Rvalue::ThreadLocalRef(_) | ||
1159 | 1159 | | Rvalue::AddressOf(_, _) | ||
1160 | - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _) | |
1160 | + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::UbCheck(_), _) | |
1161 | 1161 | | Rvalue::Discriminant(_) => {} | ||
1162 | 1162 | } | ||
1163 | 1163 | self.super_rvalue(rvalue, location); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -123,7 +123,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | ||
123 | 123 | | sym::variant_count |
124 | 124 | | sym::is_val_statically_known |
125 | 125 | | sym::ptr_mask |
126 | - | sym::debug_assertions | |
126 | + | sym::check_language_ub | |
127 | + | sym::check_library_ub | |
127 | 128 | | sym::fadd_algebraic |
128 | 129 | | sym::fsub_algebraic |
129 | 130 | | sym::fmul_algebraic |
@@ -508,7 +509,7 @@ pub fn check_intrinsic_type( | ||
508 | 509 | (0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) |
509 | 510 | } |
510 | 511 | |
511 | - sym::debug_assertions => (0, 1, Vec::new(), tcx.types.bool), | |
512 | + sym::check_language_ub | sym::check_library_ub => (0, 1, Vec::new(), tcx.types.bool), | |
512 | 513 | |
513 | 514 | sym::simd_eq |
514 | 515 | | sym::simd_ne |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -909,7 +909,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { | ||
909 | 909 | NullOp::SizeOf => write!(fmt, "SizeOf({t})"), |
910 | 910 | NullOp::AlignOf => write!(fmt, "AlignOf({t})"), |
911 | 911 | NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"), |
912 | -NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"), | |
912 | +NullOp::UbCheck(kind) => write!(fmt, "UbCheck({kind:?})"), | |
913 | 913 | } |
914 | 914 | } |
915 | 915 | ThreadLocalRef(did) => ty::tls::with(|tcx |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1361,8 +1361,13 @@ pub enum NullOp<'tcx> { | ||
1361 | 1361 | AlignOf, |
1362 | 1362 | /// Returns the offset of a field |
1363 | 1363 | OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), |
1364 | -/// cfg!(debug_assertions), but expanded in codegen | |
1365 | - DebugAssertions, | |
1364 | +UbCheck(UbKind), | |
1365 | +} | |
1366 | + | |
1367 | +#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] | |
1368 | +pub enum UbKind { | |
1369 | +LanguageUb, | |
1370 | +LibraryUb, | |
1366 | 1371 | } |
1367 | 1372 | |
1368 | 1373 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
@@ -194,7 +194,7 @@ impl<'tcx> Rvalue<'tcx> { | |||
194 | 194 | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { |
195 | 195 | tcx.types.usize | |
196 | 196 | } | |
197 | -Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool, | ||
197 | +Rvalue::NullaryOp(NullOp::UbCheck(_), _) => tcx.types.bool, | ||
198 | 198 | Rvalue::Aggregate(ref ak, ref ops) => match **ak { | |
199 | 199 | AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), | |
200 | 200 | AggregateKind::Tuple => { |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -433,7 +433,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ||||
433 | 433 | | Rvalue::Discriminant(..) | ||
434 | 434 | | Rvalue::Len(..) | ||
435 | 435 | | Rvalue::NullaryOp( | ||
436 | -NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions, | |
436 | +NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::UbCheck(_), | |
437 | 437 | _, | ||
438 | 438 | ) => {} | ||
439 | 439 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -488,7 +488,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { | ||
488 | 488 | NullOp::OffsetOf(fields) => { |
489 | 489 | layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() |
490 | 490 | } |
491 | -NullOp::DebugAssertions => return None, | |
491 | +NullOp::UbCheck(_) => return None, | |
492 | 492 | }; |
493 | 493 | let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); |
494 | 494 | let imm = ImmTy::try_from_uint(val, usize_layout)?; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -639,7 +639,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | ||
639 | 639 | NullOp::OffsetOf(fields) => { |
640 | 640 | op_layout.offset_of_subfield(self, fields.iter()).bytes() |
641 | 641 | } |
642 | -NullOp::DebugAssertions => return None, | |
642 | +NullOp::UbCheck(_) => return None, | |
643 | 643 | }; |
644 | 644 | ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() |
645 | 645 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -20,13 +20,30 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { | ||
20 | 20 | sym::unreachable => { |
21 | 21 | terminator.kind = TerminatorKind::Unreachable; |
22 | 22 | } |
23 | - sym::debug_assertions => { | |
23 | + sym::check_language_ub => { | |
24 | 24 | let target = target.unwrap(); |
25 | 25 | block.statements.push(Statement { |
26 | 26 | source_info: terminator.source_info, |
27 | 27 | kind: StatementKind::Assign(Box::new(( |
28 | 28 | *destination, |
29 | -Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool), | |
29 | +Rvalue::NullaryOp( | |
30 | +NullOp::UbCheck(UbKind::LanguageUb), | |
31 | + tcx.types.bool, | |
32 | +), | |
33 | +))), | |
34 | +}); | |
35 | + terminator.kind = TerminatorKind::Goto { target }; | |
36 | +} | |
37 | + sym::check_library_ub => { | |
38 | +let target = target.unwrap(); | |
39 | + block.statements.push(Statement { | |
40 | +source_info: terminator.source_info, | |
41 | +kind: StatementKind::Assign(Box::new(( | |
42 | +*destination, | |
43 | +Rvalue::NullaryOp( | |
44 | +NullOp::UbCheck(UbKind::LibraryUb), | |
45 | + tcx.types.bool, | |
46 | +), | |
30 | 47 | ))), |
31 | 48 | }); |
32 | 49 | terminator.kind = TerminatorKind::Goto { target }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -446,7 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> { | ||
446 | 446 | NullOp::SizeOf => {} |
447 | 447 | NullOp::AlignOf => {} |
448 | 448 | NullOp::OffsetOf(_) => {} |
449 | -NullOp::DebugAssertions => {} | |
449 | +NullOp::UbCheck(_) => {} | |
450 | 450 | }, |
451 | 451 | |
452 | 452 | Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -251,13 +251,19 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { | ||
251 | 251 | type T = stable_mir::mir::NullOp; |
252 | 252 | fn stable(&self, tables: &mut Tables<'_>) -> Self::T { |
253 | 253 | use rustc_middle::mir::NullOp::*; |
254 | +use rustc_middle::mir::UbKind; | |
254 | 255 | match self { |
255 | 256 | SizeOf => stable_mir::mir::NullOp::SizeOf, |
256 | 257 | AlignOf => stable_mir::mir::NullOp::AlignOf, |
257 | 258 | OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( |
258 | 259 | indices.iter().map(|idx |
259 | 260 | ), |
260 | -DebugAssertions => stable_mir::mir::NullOp::DebugAssertions, | |
261 | +UbCheck(UbKind::LanguageUb) => { | |
262 | + stable_mir::mir::NullOp::UbCheck(stable_mir::mir::UbKind::LanguageUb) | |
263 | +} | |
264 | +UbCheck(UbKind::LibraryUb) => { | |
265 | + stable_mir::mir::NullOp::UbCheck(stable_mir::mir::UbKind::LibraryUb) | |
266 | +} | |
261 | 267 | } |
262 | 268 | } |
263 | 269 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -515,6 +515,8 @@ symbols! { | ||
515 | 515 | cfi, |
516 | 516 | cfi_encoding, |
517 | 517 | char, |
518 | + check_language_ub, | |
519 | + check_library_ub, | |
518 | 520 | client, |
519 | 521 | clippy, |
520 | 522 | clobber_abi, |
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
@@ -639,7 +639,7 @@ impl Rvalue { | |||
639 | 639 | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { |
640 | 640 | Ok(Ty::usize_ty()) | |
641 | 641 | } | |
642 | -Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()), | ||
642 | +Rvalue::NullaryOp(NullOp::UbCheck(_), _) => Ok(Ty::bool_ty()), | ||
643 | 643 | Rvalue::Aggregate(ak, ops) => match *ak { | |
644 | 644 | AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), | |
645 | 645 | AggregateKind::Tuple => Ok(Ty::new_tuple( | |
@@ -1007,7 +1007,13 @@ pub enum NullOp { | |||
1007 | 1007 | /// Returns the offset of a field. | |
1008 | 1008 | OffsetOf(Vec<(VariantIdx, FieldIdx)>), | |
1009 | 1009 | /// cfg!(debug_assertions), but at codegen time | |
1010 | - DebugAssertions, | ||
1010 | + UbCheck(UbKind), | ||
1011 | +} | ||
1012 | + | ||
1013 | +#[derive(Clone, Debug, Eq, PartialEq)] | ||
1014 | +pub enum UbKind { | ||
1015 | +LanguageUb, | ||
1016 | +LibraryUb, | ||
1011 | 1017 | } | |
1012 | 1018 | ||
1013 | 1019 | impl Operand { |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -26,6 +26,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { | ||
26 | 26 | // SAFETY: the caller must guarantee that `i` is a valid char value. |
27 | 27 | unsafe { |
28 | 28 | assert_unsafe_precondition!( |
29 | + check_language_ub, | |
29 | 30 | "invalid value for `char`", |
30 | 31 | (i: u32 = i) => char_try_from_u32(i).is_ok() |
31 | 32 | ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -101,7 +101,11 @@ pub const unsafe fn unreachable_unchecked() -> ! { | ||
101 | 101 | // SAFETY: the safety contract for `intrinsics::unreachable` must |
102 | 102 | // be upheld by the caller. |
103 | 103 | unsafe { |
104 | - intrinsics::assert_unsafe_precondition!("hint::unreachable_unchecked must never be reached", () => false); | |
104 | + intrinsics::assert_unsafe_precondition!( | |
105 | + check_language_ub, | |
106 | +"hint::unreachable_unchecked must never be reached", | |
107 | +() => false | |
108 | +); | |
105 | 109 | intrinsics::unreachable() |
106 | 110 | } |
107 | 111 | } |
@@ -147,6 +151,7 @@ pub const unsafe fn assert_unchecked(cond: bool) { | ||
147 | 151 | // SAFETY: The caller promised `cond` is true. |
148 | 152 | unsafe { |
149 | 153 | intrinsics::assert_unsafe_precondition!( |
154 | + check_language_ub, | |
150 | 155 | "hint::assert_unchecked must never be called when the condition is false", |
151 | 156 | (cond: bool = cond) => cond, |
152 | 157 | ); |