Skip to content

hyb generate tries to read a sibling directory ending in .go #4418

Open

Description

@ub3dqy

On b1627e83b437bfc948292f17a8ce4183cef23130, hyb generate calc.hy exits 1 when the Go package directory also contains a subdirectory named nested.go. Go itself ignores that directory.

To reproduce, create go.mod with module example.com/demo and go 1.26, app.go with package demo, calc.hy with pub fn add(a int, b int) int { return a + b }, and nested.go/other.go with package other. On Windows the generator tries to read nested.go and fails. It should generate into package demo.

I have a small fix with two regression tests. The Linux workspace suite and all 139 corpus cases pass with the pinned toolchain. Would you be open to 35 USDC on Base for a PR with the fix and tests?

Dima Mak / ub3dqy

Activity

  1. dukenordj-rgb commented on Nov 13, 2026

    @dukenordj-rgb
    Contributor

    Root Cause Analysis

    The bug stems from directory traversal logic in the code generator that uses a naive suffix check (e.g., checking if a directory name ends with .go) rather than strictly inspecting file extensions or leveraging Go's standard package discovery semantics via go/packages or os.Stat checks combined with regular file filters.

    When hyb generate scans the package directory, it encounters the subdirectory named nested.go. Because the string ends in .go, the generator misinterprets the directory as a target source file, attempts to open and read it as a regular file (os.Open or equivalent), and subsequently fails with an EISDIR (on Unix-like systems) or access/read error (on Windows, where opening a directory handle for sequential file reading fails differently). Go's own toolchain correctly ignores subdirectories during package loading, even if they possess a .go extension, because source files must be regular files.

    Patch Snippet

    To fix the issue, the file discovery pass must ensure that candidate paths point to regular files and not directories, while explicitly ignoring or filtering out any directory entries regardless of their naming scheme.

    // Before: naive suffix check or unfiltered directory iteration
    if strings.HasSuffix(entry.Name(), ".go") {
        // attempts to read entry as a source file
    }
    
    // After: enforce regular file check via os.FileInfo / fs.DirEntry
    if entry.IsDir() {
        continue
    }
    
    if !strings.HasSuffix(entry.Name(), ".go") {
        continue
    }

    Ensure the traversal implementation uses fs.DirEntry.Type().IsRegular() or runs an os.Stat on the candidate path to reject directories masquerading with file-like extensions.

    Regression Test Coverage

    1. Subdirectory with .go Suffix Test:
      Create a test case workspace featuring a package directory containing a subdirectory explicitly named foo.go. Run the code generator against a valid .hy file in the root of the package. Verify that the generator completes with exit code 0 and successfully ignores the foo.go subdirectory without throwing an I/O error.

    2. Cross-Platform File System Sanity Test:
      Validate that path resolution handles trailing extension collisions across Unix and Windows directory streams, ensuring that IsDir() guards protect file-reading routines uniformly.

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