Skip to content

Module validation failed when returning different tuple types #15670

Open
@straight-shoota

Description

@straight-shoota

The following code fails codegen during LLVM's module validation on Crystal 1.16.0, but works fine in 1.15.1:

fallback = nil.as({Int32} | Nil)

ary = [] of {String}
ary.find(fallback) { }

Error message (compiler backtrace is irrelevant):

Module validation failed: PHI node operands are not the same type as the result!
  %60 = phi ptr [ zeroinitializer, %exit7 ], [ %13, %then9 ], [ %139, %exit33 ], !dbg !26

The regression was triggered by the implementation of Indexable#find from #15589, which overrides Enumerable#find. (This should probably not be an override when there's no offset parameter, but that's a different topic: #15671)
The change in #find itself is not relevant. It just made this codegen error visible.

Reduced:

def foo(x, &)
  return nil.as?({Int32}?) if x

  yield
  {""}
end

foo(1) {}
Module validation failed: PHI node operands are not the same type as the result!
  %37 = phi ptr [ zeroinitializer, %exit ], [ %5, %else ], !dbg !11

Without yield there's a similar validation error:

def bar(x)
  return nil.as?({Int32}?) if x

  {""}
end

bar(1)
Load operand must be a pointer.
  %36 = load %"(Tuple(Int32 | String) | Nil)", %Nil zeroinitializer, align 8, !dbg !19

I suspect they're different symptoms of the same issue.

The return type of both variants is Tuple(Int32 | String) | Nil.
Maybe merging the tuple types Tuple(Int32) and Tuple(String) into Tuple(Int32 |String) is causing havoc?

This bug was first discovered by @BlobCodes on https://gitlab.com/BlobCodes/pipelinecr/-/jobs/9734877094 and reported on Discord.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugA bug in the code. Does not apply to documentation, specs, etc.topic:compiler:codegen

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions