Skip to content

Commit c7e3a5d

Browse files
committed
test: reproduce _projected_ty Subslice bug in drop-glue resolution
Add two tests demonstrating that _projected_ty() returns the wrong type for Subslice projections, which can cause drop-glue edges to be lost during SMIR reduction: - Unit test: directly models Drop(local.Subslice(...)) and confirms call_edges misses the drop_in_place::<[Inner; 2]> edge because _projected_ty returns the original array type instead of the subslice result type. - Integration test: Rust program destructuring an owned array of Drop types via `let [first, rest @ ..] = arr`, generating a Subslice projection in the SMIR. Marked as expected-fail (unsupported).
1 parent 60b5e5a commit c7e3a5d

2 files changed

Lines changed: 128 additions & 0 deletions

File tree

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/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)