Skip to content

bug: struct function validation gaps — private access, nonexistent calls, struct type mismatch #1599

@SchoolyB

Description

@SchoolyB

Description

Struct function calls have three validation gaps in the typechecker. Two allow invalid code to reach C compilation and crash, and one ignores the private visibility modifier entirely.

Bug 1: Private struct functions callable from outside the struct

The private modifier on struct functions is not enforced. Private functions are callable from anywhere, not just from other functions within the same struct.

const Secret struct {
    value int

    private do hidden_calc(a int, b int) -> int {
        return a * b
    }

    do public_calc(a int, b int) -> int {
        return Secret.hidden_calc(a, b)   // Correct: internal call should work
    }
}

do main() {
    mut r int = Secret.hidden_calc(5, 6)   // Should be rejected — runs fine, prints 30
}

Expected: The typechecker should reject Secret.hidden_calc() when called from outside the struct.

Where: typechecker.c — the Type.func() call path (lines ~2382–2483) finds the function signature but never checks its visibility. After resolving the function, it needs to verify the function isn't marked private when the call site is outside the struct.

Bug 2: Nonexistent struct function passes typechecker, crashes at C compilation

Calling a function that doesn't exist on a struct produces no typechecker error. The call silently resolves to TYPE_VOID and falls through to codegen, which emits a call to a C function that doesn't exist.

const Point struct {
    x int
    y int
}

do main() {
    Point.doesnt_exist(1, 2, 3)   // No EZ error — C crash: "call to undeclared function"
}

When the result is assigned to a variable, E3038 (void assign) fires — but the real error should be "undefined function", not "void assign".

Expected: The typechecker should emit an error like "struct 'Point' has no function 'doesnt_exist'".

Where: typechecker.c lines ~2481–2483 — when find_func() returns NULL for a Type.func() call, the code silently sets result = &TYPE_VOID with no error. It should emit a diagnostic here.

Bug 3: Struct-to-struct type mismatch not caught in function args

Passing the wrong struct type to a function parameter crashes at C compilation. This affects both struct functions and regular functions — it's a general typechecker gap. Enum-to-enum mismatch IS correctly caught, but struct-to-struct is not.

const Point struct {
    x int
    y int

    do distance(a Point, b Point) -> int {
        return a.x - b.x
    }
}

const Color struct {
    r int
    g int
}

do main() {
    mut c = Color{r: 255, g: 0}
    mut p = Point{x: 1, y: 2}
    mut d int = Point.distance(c, p)   // No EZ error — C crash: incompatible struct types
}

This also crashes for regular (non-struct) functions:

do process(p Point) -> int {
    return p.x
}

do main() {
    mut c = Color{r: 255, g: 0}
    mut n int = process(c)   // Same crash
}

Expected: The typechecker should compare struct type names when both the parameter and argument are structs, and emit E3001 on mismatch.

Where: typechecker.c — the argument type validation for both regular calls (~line 3046) and struct function calls (~line 2400) compares kind values. Since both Point and Color have kind TK_STRUCT, the check passes. The fix is to also compare type->name when both sides are TK_STRUCT.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcodegenRelated to C code generationtypecheckerRelated to type checking and validation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions