Skip to content

Commit 7f78620

Browse files
committed
Coercion support: &[T;N] → &[T] unsize coercion builds length-N slice model
Add PointerCoercion::Unsize arm in rvalue_type(): reads N from the MIR source type before consuming the operand, then wraps the array place type in a (Array<Int,T>, N) tuple to produce the slice model with concrete length. Paired tests: pass accesses index 3 on a 4-element slice (safe), fail accesses index 4 → Unsat. https://claude.ai/code/session_01BV92ggaKvAp7oNknvVmGsM
1 parent 037f292 commit 7f78620

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

src/analyze/basic_block.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,27 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
659659
};
660660
PlaceType::with_ty_and_term(func_ty.vacuous(), chc::Term::null())
661661
}
662+
Rvalue::Cast(
663+
mir::CastKind::PointerCoercion(mir_ty::adjustment::PointerCoercion::Unsize, _),
664+
operand,
665+
_ty,
666+
) => {
667+
// &[T; N] → &[T]: build the slice model (Array<Int,T>, N).
668+
// Read MIR type before consuming operand.
669+
let src_mir_ty = operand.ty(&self.local_decls, self.tcx);
670+
let mir_ty::TyKind::Ref(_, inner_mir_ty, _) = src_mir_ty.kind() else {
671+
unimplemented!("Unsize coercion of non-reference: {:?}", src_mir_ty)
672+
};
673+
let mir_ty::TyKind::Array(_, len_const) = inner_mir_ty.kind() else {
674+
unimplemented!("Unsize coercion of non-array reference: {:?}", inner_mir_ty)
675+
};
676+
let n = len_const
677+
.try_to_target_usize(self.tcx)
678+
.expect("array length must be a known constant");
679+
let arr_pty = self.operand_type(operand).deref();
680+
let n_pty = PlaceType::with_ty_and_term(rty::Type::int(), chc::Term::int(n as i64));
681+
PlaceType::tuple(vec![arr_pty.boxed(), n_pty.boxed()]).immut()
682+
}
662683
Rvalue::Discriminant(place) => {
663684
let place = self.elaborate_place(&place);
664685
let ty = self.env.place_type(place);

tests/ui/fail/array_literal_2.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@error-in-other-file: Unsat
2+
//@compile-flags: -C debug-assertions=off
3+
4+
fn main() {
5+
let arr = [0i32, 0, 0, 0];
6+
let s: &[i32] = &arr;
7+
let _ = s[4];
8+
}

tests/ui/pass/array_literal_2.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@check-pass
2+
//@compile-flags: -C debug-assertions=off
3+
4+
fn main() {
5+
let arr = [0i32, 0, 0, 0];
6+
let s: &[i32] = &arr;
7+
let _ = s[3];
8+
}

0 commit comments

Comments
 (0)