Skip to content

$new(T.pointee_type) allocates wrong type when generic function is instantiated for multiple pointer types #26995

@enghitalo

Description

@enghitalo

Describe the bug

When a generic function uses $new(T.pointee_type) and is instantiated with two or more different pointer types in the same program, every instantiation generates C code that allocates the same (last-seen) pointee type rather than the per-instantiation type. The result is silently wrong code: the returned pointer's static V type is correct but the heap object behind it is of a different type, leading to memory corruption, wrong values, or runtime errors.

Introduced by 8b5f74e.

Reproduction Steps

module main

struct Foo {
    name string
}

fn make_pointer[T]() T {
    $if T.indirections == 1 {
        mut p := $new(T.pointee_type)
        return p
    } $else {
        return $zero(T)
    }
}

fn main() {
    int_ptr := make_pointer[&int]()
    foo_ptr := make_pointer[&Foo]()
    dump(*int_ptr)
    dump(*foo_ptr)
}

Expected Behavior

[file.v:18] *int_ptr: 0
[file.v:19] *foo_ptr: Foo{
    name: ''
}

Current Behavior

[file.v:18] *int_ptr: 8636372
[file.v:19] *foo_ptr: Foo{
    name: ''
}

*int_ptr reads garbage. Inspecting the generated C with v -keepc shows the make_pointer[&int] instantiation allocates a Foo, not an int:

VV_LOC int* main__make_pointer_T___ptr__int(void) {
    main__Foo* p = HEAP(main__Foo, ((main__Foo){.name = (string){.str=(byteptr)\"\", .is_lit=1},}));
    return p;
}

Both _T___ptr__int and _T___ptr__main__Foo instantiations emit HEAP(main__Foo, ...). The "last seen" pointee type wins for all instantiations.

This blocks refactoring vlib/x/json2/decode.v to use $new(T.pointee_type) instead of the manual create_decoded_ptr helper.

Possible Solution

Resolve T.pointee_type per-instantiation in the C generator instead of caching/sharing across instantiations.

V version

V 0.5.1 6dd9033.eb1d47b

Environment details

linux, Ubuntu 24.04 LTS, gcc 14.2.0, tcc 0.9.28rc

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions