Skip to content
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

Issue with "where" in a nested record #912

Open
mtdowling opened this issue Jan 16, 2025 · 2 comments
Open

Issue with "where" in a nested record #912

mtdowling opened this issue Jan 16, 2025 · 2 comments
Labels
semantics Unexpected or unsound behaviors

Comments

@mtdowling
Copy link

The generated code for a where clause doesn't include the required outer variable, causing it to evaluate to nil:

local record mod
    record Foo where self.kind == Foo
        kind: self
    end
end

local instance: mod.Foo = {kind = mod.Foo}

-- Does not work:
if instance is mod.Foo then
    print("[1] It is a Foo!")
end

-- Works:
local Foo = mod.Foo
if instance is Foo then
    print("[2] It is a Foo!")
end

Generated Lua code:

local mod = { Foo = {} }





local instance = { kind = mod.Foo }


if instance.kind == Foo then
   print("[1] It is a Foo!")
end


local Foo = mod.Foo
if instance.kind == Foo then
   print("[2] It is a Foo!")
end
@catwell
Copy link
Contributor

catwell commented Jan 16, 2025

Note that this also works:

local record mod
    record Foo where self.kind == mod.Foo
        kind: self
    end
end

local instance: mod.Foo = {kind = mod.Foo}

if instance is mod.Foo then
    print("It is a Foo!")
end

However this obviously won't:

--- foo.tl

local record mod
    record Foo where self.kind == mod.Foo
        kind: self
    end
end

return mod
--- bar.tl

local foo = require "foo"

local instance: foo.Foo = {kind = foo.Foo}

if instance is foo.Foo then
    print("It is a Foo!")
end

Running bar.tl will cause attempt to index a nil value (global 'mod').

This is not related to the nesting, this is the behavior of where clauses, e.g. this fails too (it generates a reference to sentinel which is not defined):

--- foo.tl

local sentinel = table.concat

local record Foo where self.kind == sentinel
    kind: function
end

return Foo
--- bar.tl

local Foo = require "foo"

local instance: Foo = {kind = table.concat}

if instance is Foo then
    print("It is a Foo!")
end

I have never tried using where clauses this way (with variables outside of self), I am not sure if it should be allowed. Currently they just behave like "macros" i.e. they are copied as is.

@hishamhm
Copy link
Member

Yeah, where clauses are non-hygienic macros. I think we do need to support variables outside self (since functions are variables too). For now, this is just a quirk we'll have to live with for simplicity's sake.

@hishamhm hishamhm added the semantics Unexpected or unsound behaviors label Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semantics Unexpected or unsound behaviors
Projects
None yet
Development

No branches or pull requests

3 participants