-
-
Notifications
You must be signed in to change notification settings - Fork 415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segfault when accessing a union in a tuple via Any
#4507
Comments
The match itself isn't the issue. That is fine. In the original example. This works: actor Main
let env: Env
new create(env': Env) =>
env = env'
let x = ("hello", USize(123))
match_x(x) // segfault
fun match_x(x: Any val) =>
env.out.print("match_x(x: Any val): ")
// segfault
match x
| let s: Stringable => env.out.print("\t" + s.string())
| (let a: Stringable, let b: USize) =>
env.out.print("\t(" + a.string() + ", " + b.string() +")")
else
env.out.print("\tno-match")
end So does this: actor Main
let env: Env
new create(env': Env) =>
env = env'
let x = ("hello", USize(123))
match_x(x) // segfault
fun match_x(x: Any val) =>
env.out.print("match_x(x: Any val): ")
// segfault
match x
| let s: Stringable => env.out.print("\t" + s.string())
| (let a: Stringable, let b: (USize | U64)) =>
env.out.print("hello")
else
env.out.print("\tno-match")
end The issue in the first match is with the combination of a match through the union AND the message send. What exactly is open to question. The second example is the same issue. It is matching on So there's something with the tuple being matched against a union and then PROBABLY the usage of the matched in a message send. More investigation is needed to know if it is message send is in fact fully required. Simple testing says yes. Here's a more minimal example: actor Main
let _env: Env
new create(env: Env) =>
_env = env
match_x(("hello", USize(123)))
fun match_x(x: Any val) =>
match x
| (let a: Stringable, let b: (USize | U64)) =>
_env.out.print("\t(" + b.string() +")")
end Note the following where the match is against the known tuple types is fine: actor Main
let _env: Env
new create(env: Env) =>
_env = env
match_x(("hello", USize(123)))
fun match_x(x: (Stringable, (USize | U64))) =>
match x
| (let a: Stringable, let b: (USize | U64)) =>
_env.out.print("\t(" + b.string() +")")
end |
Here's an even more minimal example: actor Main
new create(env: Env) =>
let x: Any val = ("hello", (USize(123)))
match x
| (let a: Stringable, let b: (USize | U64)) =>
env.out.print(b.string())
end |
The message send isn't required. Here's a still more minimal example: actor Main
new create(e: Env) =>
let x: Any val = ("a", (U8(1)))
match x
| (let a: String, let b: (U8 | U16)) =>
b.string()
end At this point what seems to be important is the Whoever picks this up can work more from there. |
Any
Discussed in the sync call. Listen to the sync call recording for a more detailed explanation, but what's going on here is:
To fix this, we would need the compiled code inside the match to recognize the subtle distinction between the two different tuple shapes, and generate different code for different tuple shape cases, with the one case we need here being a case where we need to generated a boxed pointer for This is non-trivial, but should be possible. |
Repro
Minimal version
Some more cases
OS: MacOS, M3
Pony version
Backtrace (of the minimal version)
The text was updated successfully, but these errors were encountered: