Skip to content

[buildable] hy-check(const_init): is_conversion_type_name accepts Rust-only type names in const initializers (HYB-E6003, Row 13) #4002

Open

Description

@bradwue313

Summary

Under GUARANTEES.md Row 13 (BUILDABLE), every program accepted by hyb check must emit Go code that passes go build (or emits via hyb emit).

Following up on #3968/#3969 in const_div_zero.rs, is_conversion_type_name in compiler/crates/hy-check/src/const_init.rs similarly includes Rust-only primitive aliases:

  • char
  • f32, f64
  • i8, i16, i32, i64
  • u8, u16, u32, u64
  • isize, usize

Consequently, constant declarations using Rust type conversions:
hy package main const x = i8(42) const y = usize(10) const z = f32(1.0)
are accepted by hyb check with 0 diagnostics (Verdict::Accept, exit 0).

Downstream hyb emit preserves the conversion call verbatim in Go emission (const x = i8(42)), and go build fails compilation:
ext undefined: i8 undefined: usize undefined: f32
violating Row 13 (BUILDABLE).

Fix & Verification

  • Removed non-Go type names (char, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64, isize, usize) from is_conversion_type_name in const_init.rs.
  • Added regression test suite compiler/crates/hy-check/tests/const_init_rust_types.rs asserting HYB-E6003 is emitted across all non-Go type conversion initializers, and standard Go types (int8, uint8, float32, complex128) accept cleanly.

Settlement Coordinates:

  • Author: @bradwue313
  • Base USDC: 0x38e0f40371be8b30f0909f890a1f701a25cd30cd
  • Solana: CRdpAku2qovsPN2wGej5AbgMNtuhRQtq3GKFDFfMkJsv

Activity

  1. dukenordj-rgb commented on Nov 7, 2026

    @dukenordj-rgb
    Contributor

    Root Cause Analysis

    The bug stems from a semantic soundness violation in hy-check regarding constant initialization validation. Specifically, the helper function is_conversion_type_name inside compiler/crates/hy-check/src/const_init.rs whitelist-filters type names permitted in explicit type-conversion expressions within const contexts.

    The implementation incorrectly included Rust-specific primitive aliases (char, f32, f64, i8-i64, u8-u64, isize, usize) instead of restricting validation strictly to Go's type system (int, float32, float64, byte, rune, etc.).

    Because hyb check accepted these expressions, no diagnostics were raised during the verification phase. However, downstream code generation (hyb emit) emitted the unadjusted syntax verbatim into the target Go module (const x = i8(42)). When the output was passed to the Go toolchain, go build rejected it with undefined identifier errors for the Rust types. This directly breaches GUARANTEES.md Row 13 (BUILDABLE), which mandates that any program accepted by hyb check must successfully compile via go build.

    Patch Implementation

    To remediate the bug, remove all Rust-only primitives from the validation set in compiler/crates/hy-check/src/const_init.rs so that hyb check flags them under error code HYB-E6003.

    // compiler/crates/hy-check/src/const_init.rs
    
    /// Determines whether a type name identifier is a valid target for 
    /// explicit type conversions inside constant initializers.
    fn is_conversion_type_name(name: &str) -> bool {
        matches!(
            name,
            // Valid Go numeric/string/boolean primitive type names
            | "bool"
            | "string"
            | "int"
            | "int8"
            | "int16"
            | "int32"
            | "int64"
            | "uint"
            | "uint8"
            | "uint16"
            | "uint32"
            | "uint64"
            | "uintptr"
            | "byte"
            | "rune"
            | "float32"
            | "float64"
            | "complex64"
            | "complex128"
        )
    }

    Regression Test Coverage

    Add an integration test suite under compiler/crates/hy-check/tests/const_init_rust_types.rs to verify that HYB-E6003 is correctly emitted for all forbidden type conversions, while valid Go standard types pass without diagnostics.

    // compiler/crates/hy-check/tests/const_init_rust_types.rs
    
    use hy_check::check_source;
    use hy_diagnostics::ErrorCode;
    
    #[test]
    fn test_rust_only_type_conversions_rejected() {
        let source = r#"
            package main
            const a = i8(42)
            const b = usize(10)
            const c = f32(1.0)
            const d = char(65)
        "#;
    
        let diagnostics = check_source(source);
        assert_eq!(diagnostics.len(), 4);
        for diag in diagnostics {
            assert_eq!(diag.code, ErrorCode::Custom("HYB-E6003".into()));
        }
    }
    
    #[test]
    fn test_valid_go_type_conversions_accepted() {
        let source = r#"
            package main
            const a = int8(42)
            const b = uint64(10)
            const c = float32(1.0)
            const d = rune(65)
        "#;
    
        let diagnostics = check_source(source);
        assert!(diagnostics.is_empty(), "Expected clean compilation for Go types");
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions