Skip to content

Commit 575b6ed

Browse files
committed
test(prove-rs): add subslice-drop-unsupported-fail repro
Add integration test for Subslice projection on an owned array of Drop types. The `let [first, rest @ ..]` pattern generates a Subslice that changes the type from [Droppable; 3] to [Droppable; 2], exercising an unsupported code path in _projected_ty() and K semantics. Marked as expected-fail with show snapshot.
1 parent 60b5e5a commit 575b6ed

4 files changed

Lines changed: 185 additions & 0 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
┌─ 1 (root, init)
3+
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
4+
│ span: 0
5+
6+
│ (90 steps)
7+
├─ 3
8+
│ #setLocalValue ( place ( ... local: local ( 1 ) , projection: .ProjectionElems )
9+
│ function: main
10+
│ span: 64
11+
12+
│ (4 steps)
13+
├─ 4
14+
│ #execStmt ( statement ( ... kind: statementKindAssign ( ... place: place ( ... l
15+
│ function: main
16+
│ span: 64
17+
18+
┃ (1 step)
19+
┣━━┓
20+
┃ │
21+
┃ ├─ 5
22+
┃ │ #setLocalValue ( place ( ... local: local ( 7 ) , projection: .ProjectionElems )
23+
┃ │ function: main
24+
┃ │ span: 54
25+
┃ │
26+
┃ │ (2 steps)
27+
┃ └─ 8 (vacuous, leaf)
28+
┃ operandCopy ( place ( ... local: local ( 5 ) , projection: projectionElemField (
29+
┃ function: main
30+
┃ span: 54
31+
32+
┣━━┓
33+
┃ │
34+
┃ ├─ 6
35+
┃ │ #setLocalValue ( place ( ... local: local ( 7 ) , projection: .ProjectionElems )
36+
┃ │ function: main
37+
┃ │ span: 54
38+
┃ │
39+
┃ │ (1 step)
40+
┃ └─ 9 (vacuous, leaf)
41+
┃ #evalUnion ( rvalueUse ( operandCopy ( place ( ... local: local ( 5 ) , projecti
42+
┃ function: main
43+
┃ span: 54
44+
45+
┗━━┓
46+
47+
└─ 7 (stuck, leaf)
48+
#execStmt ( statement ( ... kind: statementKindAssign ( ... place: place ( ... l
49+
function: main
50+
span: 64
51+
52+
53+
┌─ 2 (root, leaf, target, terminal)
54+
│ #EndProgram ~> .K
55+
56+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Reproducer: Subslice projection on an array of Drop types.
2+
//
3+
// `let [first, rest @ ..] = arr` generates a Subslice projection that
4+
// changes the type from [Droppable; 3] to [Droppable; 2]. The SMIR
5+
// linker's _projected_ty() currently returns the original array type
6+
// for Subslice, which could cause drop-glue mis-resolution when
7+
// Subslice projections appear in Drop terminator places.
8+
9+
struct Droppable(u8);
10+
11+
impl Drop for Droppable {
12+
fn drop(&mut self) {}
13+
}
14+
15+
fn main() {
16+
let arr = [Droppable(1), Droppable(2), Droppable(3)];
17+
let [first, rest @ ..] = arr;
18+
assert!(first.0 == 1);
19+
assert!(rest[0].0 == 2);
20+
assert!(rest[1].0 == 3);
21+
}

kmir/src/tests/integration/test_integration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
'ptr-cast-array-to-nested-wrapper-fail',
7171
'ptr-cast-array-to-singleton-wrapped-array-fail',
7272
'iterator-simple-fail',
73+
'subslice-drop-unsupported-fail',
7374
]
7475

7576

kmir/src/tests/unit/test_smir.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,110 @@ def test_drop_function_tys_accept_core_drop_in_place_names() -> None:
258258
)
259259

260260
assert smir_info.drop_function_tys == {2: 12}
261+
262+
263+
def test_call_edges_preserve_drop_glue_for_subslice_projection() -> None:
264+
# This SMIR models:
265+
# local 1: [Inner; 3] (ty 1, ArrayType with elem_type 2)
266+
# Drop(local 1 . Subslice { from: 1, to: 3, from_end: false })
267+
#
268+
# The Subslice produces [Inner; 2] (ty 5), NOT the original [Inner; 3].
269+
# _projected_ty() currently returns the original array type (ty 1),
270+
# so drop_in_place::<[Inner; 2]> is not found and the edge is lost.
271+
smir_info = SMIRInfo(
272+
{
273+
'name': 'drop-subslice',
274+
'allocs': [],
275+
'types': [
276+
[1, {'ArrayType': {'elem_type': 2, 'size': None}}], # [Inner; 3]
277+
[
278+
2,
279+
{
280+
'StructType': {
281+
'name': 'Inner',
282+
'adt_def': 2,
283+
'fields': [],
284+
'layout': None,
285+
}
286+
},
287+
],
288+
[3, {'PtrType': {'pointee_type': 2}}],
289+
[5, {'ArrayType': {'elem_type': 2, 'size': None}}], # [Inner; 2]
290+
[6, {'PtrType': {'pointee_type': 5}}],
291+
],
292+
'functions': [
293+
[10, {'NormalSym': 'caller'}],
294+
[12, {'NormalSym': 'drop_inner'}],
295+
[14, {'NormalSym': 'drop_inner_array2'}],
296+
],
297+
'items': [
298+
{
299+
'symbol_name': 'caller',
300+
'mono_item_kind': {
301+
'MonoItemFn': {
302+
'name': 'caller',
303+
'body': {
304+
'arg_count': 0,
305+
'locals': [{'ty': 0}, {'ty': 1}],
306+
'blocks': [
307+
{
308+
'terminator': {
309+
'kind': {
310+
'Drop': {
311+
'place': {
312+
'local': 1,
313+
'projection': [
314+
{'Subslice': {'from': 1, 'to': 3, 'from_end': False}}
315+
],
316+
},
317+
'target': 0,
318+
'unwind': 'Continue',
319+
}
320+
}
321+
}
322+
}
323+
],
324+
},
325+
}
326+
},
327+
},
328+
{
329+
'symbol_name': 'drop_inner',
330+
'mono_item_kind': {
331+
'MonoItemFn': {
332+
'name': 'std::ptr::drop_in_place::<Inner>',
333+
'body': {
334+
'arg_count': 1,
335+
'locals': [{'ty': 0}, {'ty': 3}],
336+
'blocks': [],
337+
},
338+
}
339+
},
340+
},
341+
{
342+
'symbol_name': 'drop_inner_array2',
343+
'mono_item_kind': {
344+
'MonoItemFn': {
345+
'name': 'std::ptr::drop_in_place::<[Inner; 2]>',
346+
'body': {
347+
'arg_count': 1,
348+
'locals': [{'ty': 0}, {'ty': 6}],
349+
'blocks': [],
350+
},
351+
}
352+
},
353+
},
354+
],
355+
'spans': [],
356+
}
357+
)
358+
359+
# BUG: _projected_ty returns ty 1 ([Inner; 3]) for the Subslice, so
360+
# call_edges looks up drop_function_tys[1] instead of [5]. Since
361+
# drop_in_place::<[Inner; 3]> doesn't exist (only drop_in_place::<[Inner; 2]>
362+
# does), the edge is lost.
363+
#
364+
# When this is fixed, the assertion should become:
365+
# assert smir_info.call_edges == {10: {14}, 12: set(), 14: set()}
366+
# For now, document the current (buggy) behavior:
367+
assert smir_info.call_edges == {10: set(), 12: set(), 14: set()}

0 commit comments

Comments
 (0)