Skip to content

Commit 0c96061

Browse files
committed
Auto merge of #126274 - jieyouxu:rollup-uj93sfm, r=jieyouxu
Rollup of 5 pull requests Successful merges: - #126186 (Migrate `run-make/multiple-emits` to `rmake.rs`) - #126236 (Delegation: fix ICE on recursive delegation) - #126254 (Remove ignore-cross-compile directive from ui/macros/proc_macro) - #126258 (Do not define opaque types when selecting impls) - #126265 (interpret: ensure we check bool/char for validity when they are used in a cast) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 20ba13c + cfd48bd commit 0c96061

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+377
-120
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
6767
return false;
6868
};
6969
if let Some(local_sig_id) = sig_id.as_local() {
70-
self.resolver.delegation_fn_sigs[&local_sig_id].has_self
70+
// The value may be missing due to recursive delegation.
71+
// Error will be emmited later during HIR ty lowering.
72+
self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
7173
} else {
7274
match self.tcx.def_kind(sig_id) {
7375
DefKind::Fn => false,

compiler/rustc_const_eval/src/interpret/cast.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
274274
// Let's make sure v is sign-extended *if* it has a signed type.
275275
let signed = src_layout.abi.is_signed(); // Also asserts that abi is `Scalar`.
276276

277-
let v = scalar.to_bits(src_layout.size)?;
278-
let v = if signed { self.sign_extend(v, src_layout) } else { v };
279-
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
277+
let v = match src_layout.ty.kind() {
278+
Uint(_) | RawPtr(..) | FnPtr(..) => scalar.to_uint(src_layout.size)?,
279+
Int(_) => scalar.to_int(src_layout.size)? as u128, // we will cast back to `i128` below if the sign matters
280+
Bool => scalar.to_bool()?.into(),
281+
Char => scalar.to_char()?.into(),
282+
_ => span_bug!(self.cur_span(), "invalid int-like cast from {}", src_layout.ty),
283+
};
280284

281285
Ok(match *cast_ty.kind() {
282286
// int -> int

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
197197
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
198198
let layout_val = self.layout_of(instance_args.type_at(0))?;
199199
let val = self.read_scalar(&args[0])?;
200-
let val_bits = val.to_bits(layout_val.size)?;
200+
let val_bits = val.to_bits(layout_val.size)?; // sign is ignored here
201201

202202
let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
203203
let raw_shift = self.read_scalar(&args[1])?;
@@ -484,7 +484,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
484484
ret_layout: TyAndLayout<'tcx>,
485485
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
486486
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
487-
let bits = val.to_bits(layout.size)?;
487+
let bits = val.to_bits(layout.size)?; // these operations all ignore the sign
488488
let extra = 128 - u128::from(layout.size.bits());
489489
let bits_out = match name {
490490
sym::ctpop => u128::from(bits.count_ones()),
@@ -519,6 +519,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
519519
// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
520520
// First, check x % y != 0 (or if that computation overflows).
521521
let rem = self.binary_op(BinOp::Rem, a, b)?;
522+
// sign does not matter for 0 test, so `to_bits` is fine
522523
if rem.to_scalar().to_bits(a.layout.size)? != 0 {
523524
throw_ub_custom!(
524525
fluent::const_eval_exact_div_has_remainder,
@@ -545,22 +546,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
545546
self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair();
546547
Ok(if overflowed.to_bool()? {
547548
let size = l.layout.size;
548-
let num_bits = size.bits();
549549
if l.layout.abi.is_signed() {
550550
// For signed ints the saturated value depends on the sign of the first
551551
// term since the sign of the second term can be inferred from this and
552552
// the fact that the operation has overflowed (if either is 0 no
553553
// overflow can occur)
554-
let first_term: u128 = l.to_scalar().to_bits(l.layout.size)?;
555-
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
556-
if first_term_positive {
554+
let first_term: i128 = l.to_scalar().to_int(l.layout.size)?;
555+
if first_term >= 0 {
557556
// Negative overflow not possible since the positive first term
558557
// can only increase an (in range) negative term for addition
559-
// or corresponding negated positive term for subtraction
558+
// or corresponding negated positive term for subtraction.
560559
Scalar::from_int(size.signed_int_max(), size)
561560
} else {
562-
// Positive overflow not possible for similar reason
563-
// max negative
561+
// Positive overflow not possible for similar reason.
564562
Scalar::from_int(size.signed_int_min(), size)
565563
}
566564
} else {

compiler/rustc_const_eval/src/interpret/operator.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -437,23 +437,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
437437
};
438438
Ok(ImmTy::from_scalar(res, layout))
439439
}
440-
_ if layout.ty.is_integral() => {
441-
let val = val.to_scalar();
442-
let val = val.to_bits(layout.size)?;
440+
ty::Int(..) => {
441+
let val = val.to_scalar().to_int(layout.size)?;
443442
let res = match un_op {
444-
Not => self.truncate(!val, layout), // bitwise negation, then truncate
445-
Neg => {
446-
// arithmetic negation
447-
assert!(layout.abi.is_signed());
448-
let val = self.sign_extend(val, layout) as i128;
449-
let res = val.wrapping_neg();
450-
let res = res as u128;
451-
// Truncate to target type.
452-
self.truncate(res, layout)
453-
}
443+
Not => !val,
444+
Neg => val.wrapping_neg(),
454445
_ => span_bug!(self.cur_span(), "Invalid integer op {:?}", un_op),
455446
};
456-
Ok(ImmTy::from_uint(res, layout))
447+
let res = ScalarInt::truncate_from_int(res, layout.size).0;
448+
Ok(ImmTy::from_scalar(res.into(), layout))
449+
}
450+
ty::Uint(..) => {
451+
let val = val.to_scalar().to_uint(layout.size)?;
452+
let res = match un_op {
453+
Not => !val,
454+
_ => span_bug!(self.cur_span(), "Invalid unsigned integer op {:?}", un_op),
455+
};
456+
let res = ScalarInt::truncate_from_uint(res, layout.size).0;
457+
Ok(ImmTy::from_scalar(res.into(), layout))
457458
}
458459
ty::RawPtr(..) => {
459460
assert_eq!(un_op, PtrMetadata);

compiler/rustc_middle/src/ty/consts/int.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ impl ScalarInt {
209209

210210
#[inline]
211211
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
212-
let data = i.into();
213-
if size.truncate(data) == data { Some(Self::raw(data, size)) } else { None }
212+
let (r, overflow) = Self::truncate_from_uint(i, size);
213+
if overflow { None } else { Some(r) }
214214
}
215215

216216
/// Returns the truncated result, and whether truncation changed the value.
@@ -223,20 +223,15 @@ impl ScalarInt {
223223

224224
#[inline]
225225
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
226-
let i = i.into();
227-
// `into` performed sign extension, we have to truncate
228-
let truncated = size.truncate(i as u128);
229-
if size.sign_extend(truncated) as i128 == i {
230-
Some(Self::raw(truncated, size))
231-
} else {
232-
None
233-
}
226+
let (r, overflow) = Self::truncate_from_int(i, size);
227+
if overflow { None } else { Some(r) }
234228
}
235229

236230
/// Returns the truncated result, and whether truncation changed the value.
237231
#[inline]
238232
pub fn truncate_from_int(i: impl Into<i128>, size: Size) -> (Self, bool) {
239233
let data = i.into();
234+
// `into` performed sign extension, we have to truncate
240235
let r = Self::raw(size.truncate(data as u128), size);
241236
(r, size.sign_extend(r.data) as i128 != data)
242237
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2563,7 +2563,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25632563
let InferOk { obligations, .. } = self
25642564
.infcx
25652565
.at(&cause, obligation.param_env)
2566-
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
2566+
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
25672567
.map_err(|e| {
25682568
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
25692569
})?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Make sure we find these even with many checks disabled.
2+
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
3+
#![feature(core_intrinsics)]
4+
#![feature(custom_mir)]
5+
6+
use std::intrinsics::mir::*;
7+
8+
#[custom_mir(dialect = "runtime", phase = "optimized")]
9+
fn cast(ptr: *const char) -> u32 {
10+
mir! {
11+
{
12+
RET = *ptr as u32; //~ERROR: interpreting an invalid 32-bit value as a char
13+
Return()
14+
}
15+
}
16+
}
17+
18+
pub fn main() {
19+
let v = u32::MAX;
20+
cast(&v as *const u32 as *const char);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: interpreting an invalid 32-bit value as a char: $HEX
2+
--> $DIR/invalid_char_cast.rs:LL:CC
3+
|
4+
LL | RET = *ptr as u32;
5+
| ^^^^^^^^^^^^^^^^^ interpreting an invalid 32-bit value as a char: $HEX
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `cast` at $DIR/invalid_char_cast.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/invalid_char_cast.rs:LL:CC
13+
|
14+
LL | cast(&v as *const u32 as *const char);
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to 1 previous error
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Make sure we find these even with many checks disabled.
2+
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
3+
#![feature(core_intrinsics)]
4+
#![feature(custom_mir)]
5+
6+
use std::intrinsics::mir::*;
7+
8+
#[custom_mir(dialect = "runtime", phase = "optimized")]
9+
fn switch_int(ptr: *const char) {
10+
mir! {
11+
{
12+
match *ptr { //~ERROR: interpreting an invalid 32-bit value as a char
13+
'0' => ret,
14+
_ => ret,
15+
}
16+
}
17+
ret = {
18+
Return()
19+
}
20+
}
21+
}
22+
23+
pub fn main() {
24+
let v = u32::MAX;
25+
switch_int(&v as *const u32 as *const char);
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: Undefined Behavior: interpreting an invalid 32-bit value as a char: $HEX
2+
--> $DIR/invalid_char_match.rs:LL:CC
3+
|
4+
LL | / match *ptr {
5+
LL | | '0' => ret,
6+
LL | | _ => ret,
7+
LL | | }
8+
| |_____________^ interpreting an invalid 32-bit value as a char: $HEX
9+
|
10+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
11+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
12+
= note: BACKTRACE:
13+
= note: inside `switch_int` at $DIR/invalid_char_match.rs:LL:CC
14+
note: inside `main`
15+
--> $DIR/invalid_char_match.rs:LL:CC
16+
|
17+
LL | switch_int(&v as *const u32 as *const char);
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
20+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
21+
22+
error: aborting due to 1 previous error
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Make sure we find these even with many checks disabled.
2+
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
3+
4+
#[derive(Copy, Clone)]
5+
#[allow(unused)]
6+
enum E {A, B, C }
7+
8+
fn cast(ptr: *const E) { unsafe {
9+
let _val = *ptr as u32; //~ERROR: enum value has invalid tag
10+
}}
11+
12+
pub fn main() {
13+
let v = u32::MAX;
14+
cast(&v as *const u32 as *const E);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: enum value has invalid tag: 0xff
2+
--> $DIR/invalid_enum_cast.rs:LL:CC
3+
|
4+
LL | let _val = *ptr as u32;
5+
| ^^^^^^^^^^^ enum value has invalid tag: 0xff
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `cast` at $DIR/invalid_enum_cast.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/invalid_enum_cast.rs:LL:CC
13+
|
14+
LL | cast(&v as *const u32 as *const E);
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to 1 previous error
20+

src/tools/run-make-support/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ pub fn htmldocck() -> Command {
8282
python
8383
}
8484

85+
/// Returns the path for a local test file.
86+
pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
87+
cwd().join(p.as_ref())
88+
}
89+
8590
/// Path to the root rust-lang/rust source checkout.
8691
pub fn source_root() -> PathBuf {
8792
env_var("SOURCE_ROOT").into()

src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ run-make/mismatching-target-triples/Makefile
144144
run-make/missing-crate-dependency/Makefile
145145
run-make/mixing-libs/Makefile
146146
run-make/msvc-opt-minsize/Makefile
147-
run-make/multiple-emits/Makefile
148147
run-make/native-link-modifier-bundle/Makefile
149148
run-make/native-link-modifier-verbatim-linker/Makefile
150149
run-make/native-link-modifier-verbatim-rustc/Makefile

tests/crashes/124347.rs

-4
This file was deleted.

tests/run-make/multiple-emits/Makefile

-7
This file was deleted.
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use run_make_support::{cwd, path, rustc};
2+
3+
fn main() {
4+
rustc().input("foo.rs").emit("asm,llvm-ir").output("out").run();
5+
6+
assert!(path("out.ll").is_file());
7+
assert!(path("out.s").is_file());
8+
9+
rustc().input("foo.rs").emit("asm,llvm-ir").output("out2.ext").run();
10+
11+
assert!(path("out2.ll").is_file());
12+
assert!(path("out2.s").is_file());
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const fn bool_cast(ptr: *const bool) { unsafe {
2+
let _val = *ptr as u32; //~ERROR: evaluation of constant value failed
3+
//~^ interpreting an invalid 8-bit value as a bool
4+
}}
5+
6+
const _: () = {
7+
let v = 3_u8;
8+
bool_cast(&v as *const u8 as *const bool);
9+
};
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0080]: evaluation of constant value failed
2+
--> $DIR/ub-invalid-values.rs:2:16
3+
|
4+
LL | let _val = *ptr as u32;
5+
| ^^^^^^^^^^^ interpreting an invalid 8-bit value as a bool: 0x03
6+
|
7+
note: inside `bool_cast`
8+
--> $DIR/ub-invalid-values.rs:2:16
9+
|
10+
LL | let _val = *ptr as u32;
11+
| ^^^^^^^^^^^
12+
note: inside `_`
13+
--> $DIR/ub-invalid-values.rs:8:5
14+
|
15+
LL | bool_cast(&v as *const u8 as *const bool);
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
18+
error: aborting due to 1 previous error
19+
20+
For more information about this error, try `rustc --explain E0080`.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(fn_delegation)]
2+
#![allow(incomplete_features)]
3+
4+
trait Trait {
5+
reuse Trait::foo { &self.0 }
6+
//~^ ERROR recursive delegation is not supported yet
7+
}
8+
9+
reuse foo;
10+
//~^ ERROR recursive delegation is not supported yet
11+
12+
fn main() {}

0 commit comments

Comments
 (0)