Skip to content

Commit 3b418b1

Browse files
committed
Auto merge of rust-lang#3940 - rust-lang:refutable_slice, r=RalfJung
Prefer refutable slice patterns over len check + index op Just something I noticed while reviewing other PRs We do it for shim arguments almost everywhere, but when the size is not statically known, we didn't use the helpers as they rely on array ops. But we can avoid a len check followed by several index ops by just using a refutable slice pattern with `let else`. The pattern is so common, it seems almost worth a dedicated macro
2 parents eb97047 + f46e162 commit 3b418b1

File tree

5 files changed

+34
-33
lines changed

5 files changed

+34
-33
lines changed

src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -859,14 +859,15 @@ impl Tree {
859859
) -> Option<UniIndex> {
860860
let node = self.nodes.get(idx).unwrap();
861861

862+
let [child_idx] = node.children[..] else { return None };
863+
862864
// We never want to replace the root node, as it is also kept in `root_ptr_tags`.
863-
if node.children.len() != 1 || live.contains(&node.tag) || node.parent.is_none() {
865+
if live.contains(&node.tag) || node.parent.is_none() {
864866
return None;
865867
}
866868
// Since protected nodes are never GC'd (see `borrow_tracker::FrameExtra::visit_provenance`),
867869
// we know that `node` is not protected because otherwise `live` would
868870
// have contained `node.tag`.
869-
let child_idx = node.children[0];
870871
let child = self.nodes.get(child_idx).unwrap();
871872
// Check that for that one child, `can_be_replaced_by_child` holds for the permission
872873
// on all locations.

src/tools/miri/src/shims/unix/fd.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -481,14 +481,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
481481
fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
482482
let this = self.eval_context_mut();
483483

484-
if args.len() < 2 {
484+
let [fd_num, cmd, ..] = args else {
485485
throw_ub_format!(
486486
"incorrect number of arguments for fcntl: got {}, expected at least 2",
487487
args.len()
488488
);
489-
}
490-
let fd_num = this.read_scalar(&args[0])?.to_i32()?;
491-
let cmd = this.read_scalar(&args[1])?.to_i32()?;
489+
};
490+
let fd_num = this.read_scalar(fd_num)?.to_i32()?;
491+
let cmd = this.read_scalar(cmd)?.to_i32()?;
492492

493493
// We only support getting the flags for a descriptor.
494494
if cmd == this.eval_libc_i32("F_GETFD") {
@@ -508,13 +508,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
508508
// because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
509509
// differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor,
510510
// thus they can share the same implementation here.
511-
if args.len() < 3 {
511+
let [_, _, start, ..] = args else {
512512
throw_ub_format!(
513513
"incorrect number of arguments for fcntl with cmd=`F_DUPFD`/`F_DUPFD_CLOEXEC`: got {}, expected at least 3",
514514
args.len()
515515
);
516-
}
517-
let start = this.read_scalar(&args[2])?.to_i32()?;
516+
};
517+
let start = this.read_scalar(start)?.to_i32()?;
518518

519519
match this.machine.fds.get(fd_num) {
520520
Some(fd) =>

src/tools/miri/src/shims/unix/fs.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -433,18 +433,18 @@ fn maybe_sync_file(
433433
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
434434
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
435435
fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
436-
if args.len() < 2 {
436+
let [path_raw, flag, ..] = args else {
437437
throw_ub_format!(
438438
"incorrect number of arguments for `open`: got {}, expected at least 2",
439439
args.len()
440440
);
441-
}
441+
};
442442

443443
let this = self.eval_context_mut();
444444

445-
let path_raw = this.read_pointer(&args[0])?;
445+
let path_raw = this.read_pointer(path_raw)?;
446446
let path = this.read_path_from_c_str(path_raw)?;
447-
let flag = this.read_scalar(&args[1])?.to_i32()?;
447+
let flag = this.read_scalar(flag)?.to_i32()?;
448448

449449
let mut options = OpenOptions::new();
450450

src/tools/miri/src/shims/unix/linux/foreign_items.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
122122
id if id == sys_getrandom => {
123123
// Used by getrandom 0.1
124124
// The first argument is the syscall id, so skip over it.
125-
if args.len() < 4 {
125+
let [_, ptr, len, flags, ..] = args else {
126126
throw_ub_format!(
127127
"incorrect number of arguments for `getrandom` syscall: got {}, expected at least 4",
128128
args.len()
129129
);
130-
}
130+
};
131131

132-
let ptr = this.read_pointer(&args[1])?;
133-
let len = this.read_target_usize(&args[2])?;
132+
let ptr = this.read_pointer(ptr)?;
133+
let len = this.read_target_usize(len)?;
134134
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
135135
// neither of which have any effect on our current PRNG.
136136
// See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
137-
let _flags = this.read_scalar(&args[3])?.to_i32()?;
137+
let _flags = this.read_scalar(flags)?.to_i32()?;
138138

139139
this.gen_random(ptr, len)?;
140140
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;

src/tools/miri/src/shims/unix/linux/sync.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ pub fn futex<'tcx>(
1515
// may or may not be left out from the `syscall()` call.
1616
// Therefore we don't use `check_arg_count` here, but only check for the
1717
// number of arguments to fall within a range.
18-
if args.len() < 3 {
18+
let [addr, op, val, ..] = args else {
1919
throw_ub_format!(
2020
"incorrect number of arguments for `futex` syscall: got {}, expected at least 3",
2121
args.len()
2222
);
23-
}
23+
};
2424

2525
// The first three arguments (after the syscall number itself) are the same to all futex operations:
2626
// (int *addr, int op, int val).
2727
// We checked above that these definitely exist.
28-
let addr = this.read_pointer(&args[0])?;
29-
let op = this.read_scalar(&args[1])?.to_i32()?;
30-
let val = this.read_scalar(&args[2])?.to_i32()?;
28+
let addr = this.read_pointer(addr)?;
29+
let op = this.read_scalar(op)?.to_i32()?;
30+
let val = this.read_scalar(val)?.to_i32()?;
3131

3232
// This is a vararg function so we have to bring our own type for this pointer.
3333
let addr = this.ptr_to_mplace(addr, this.machine.layouts.i32);
@@ -55,15 +55,15 @@ pub fn futex<'tcx>(
5555
let wait_bitset = op & !futex_realtime == futex_wait_bitset;
5656

5757
let bitset = if wait_bitset {
58-
if args.len() < 6 {
58+
let [_, _, _, timeout, uaddr2, bitset, ..] = args else {
5959
throw_ub_format!(
6060
"incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT_BITSET`: got {}, expected at least 6",
6161
args.len()
6262
);
63-
}
64-
let _timeout = this.read_pointer(&args[3])?;
65-
let _uaddr2 = this.read_pointer(&args[4])?;
66-
this.read_scalar(&args[5])?.to_u32()?
63+
};
64+
let _timeout = this.read_pointer(timeout)?;
65+
let _uaddr2 = this.read_pointer(uaddr2)?;
66+
this.read_scalar(bitset)?.to_u32()?
6767
} else {
6868
if args.len() < 4 {
6969
throw_ub_format!(
@@ -183,15 +183,15 @@ pub fn futex<'tcx>(
183183
// Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up.
184184
op if op == futex_wake || op == futex_wake_bitset => {
185185
let bitset = if op == futex_wake_bitset {
186-
if args.len() < 6 {
186+
let [_, _, _, timeout, uaddr2, bitset, ..] = args else {
187187
throw_ub_format!(
188188
"incorrect number of arguments for `futex` syscall with `op=FUTEX_WAKE_BITSET`: got {}, expected at least 6",
189189
args.len()
190190
);
191-
}
192-
let _timeout = this.read_pointer(&args[3])?;
193-
let _uaddr2 = this.read_pointer(&args[4])?;
194-
this.read_scalar(&args[5])?.to_u32()?
191+
};
192+
let _timeout = this.read_pointer(timeout)?;
193+
let _uaddr2 = this.read_pointer(uaddr2)?;
194+
this.read_scalar(bitset)?.to_u32()?
195195
} else {
196196
u32::MAX
197197
};

0 commit comments

Comments
 (0)