Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/analyze/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,24 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
_ => unimplemented!("aggregate kind: {:?}", kind),
}
}
Rvalue::Repeat(operand, count) => {
// TODO: Stop embedding knowledge of `<[T; N] as Model>::Ty` in the analyzer
let count = count
.try_to_target_usize(self.tcx)
.expect("array repeat count must be a known constant");
let mir_elem_ty = operand.ty(&self.body.local_decls, self.tcx);
let elem_ty = self.type_builder.build(mir_elem_ty).vacuous();
let mut builder = PlaceTypeBuilder::default();
let (_, elem_term) = builder.subsume(self.operand_type(operand));
let mut seq = chc::Term::seq_empty(elem_ty.to_sort());
for _ in 0..count {
seq = seq.seq_concat(elem_term.clone().seq_unit());
Comment on lines +744 to +745

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid expanding repeat expressions one element at a time

For valid repeat arrays with counts in the thousands, this loop creates a deeply nested seq.++ term and crashes Thrust before the solver runs. Using the built thrust-rustc, [7i32; 5000] reliably overflowed rustc's stack, while a count of 1000 already produced an 18 MB SMT file. Compact repeat arrays are common for buffers, so the sequence needs a non-linearly nested representation or explicit handling for large counts.

Useful? React with 馃憤聽/ 馃憥.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm merging this for now and I'll follow-up with another (possible more effective?) option

}
builder.build(
rty::Type::Seq(Box::new(rty::RefinedType::unrefined(elem_ty))),
seq,
)
}
Rvalue::Cast(
mir::CastKind::PointerCoercion(
mir_ty::adjustment::PointerCoercion::ReifyFnPointer,
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/fail/array_repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@error-in-other-file: Unsat
//@compile-flags: -C debug-assertions=off
//@rustc-env: THRUST_SOLVER=tests/thrust-pcsat-wrapper

fn main() {
let arr = [7i32; 4];
let s: &[i32] = &arr;
assert!(s.len() == 4);
assert!(s[3] == 8);
}
10 changes: 10 additions & 0 deletions tests/ui/pass/array_repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@check-pass
//@compile-flags: -C debug-assertions=off
//@rustc-env: THRUST_SOLVER=tests/thrust-pcsat-wrapper

fn main() {
let arr = [7i32; 4];
let s: &[i32] = &arr;
assert!(s.len() == 4);
assert!(s[3] == 7);
}
Loading