teal-language / tl

The compiler for Teal, a typed dialect of Lua
MIT License
2.15k stars 111 forks source link

Compiler crash: `attempt to index a nil value (local 't')` when using require and colon syntax (:) #465

Closed jparoz closed 3 years ago

jparoz commented 3 years ago

I have been trying out Teal, and as a part of trying to convert an existing toy project from Lua to Teal, I've written vector.d.tl, a type definition file for a vector library used in the project. After writing a definition file that I was happy with, and was typechecking correctly and working with the library (invoked something like tl run main.lua), I tried requiring inspect.lua, and I was greeted with a stack traceback in tl.lua. It seems to be quite a sensitive crash; in trying to reduce the code to reproduce, at least two things seemed to be involved: the colon method syntax being used in the library, and requiring a second library afterwards.

In particular, this crash is caused by requiring a .lua library with an accompanying .d.tl file; this does not seem to happen when requiring a native .tl file.

tl --version: 0.13.1+dev (https://github.com/teal-language/tl/commit/3ae91aed06bc608fcf9ae303b4847e499952e118)

Steps to reproduce:

  1. Ensure that inspect.lua is in LUA_PATH (e.g. luarocks install inspect)
  2. Ensure that inspect.d.tl is in LUA_PATH (I used the one from teal-language/teal-types)
  3. Run tl run main.tl, see that it runs with no issues
  4. Switch the function headers of the replace function to use method syntax (lines 9, 10 of vector.lua)
  5. Run tl run main.tl, see that it dumps the stack
  6. Switch the order of the requires (lines 1, 2 of main.tl)
  7. Run tl run main.tl, see that it runs with no issues

main.tl:

local Vector = require "vector"
local inspect = require "inspect"

local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)

print("before replace: ", v1.x, v1.y)
v1:replace(v2)
print(" after replace: ", v1.x, v1.y)

vector.lua:

local module = {}
local Vector = {}
Vector.__index = Vector

module.new = function(x,y)
  return setmetatable({x=x or 0, y=y or 0}, Vector)
end

-- function Vector:replace(v)
Vector.replace = function(self, v)
    self.x, self.y = v.x, v.y
    return self
end

return module

vector.d.tl:

local record module
    new: function(number, number): Vector
end

local record Vector
    x: number
    y: number

    replace: function(Vector, Vector): Vector
end

return module

Paste of stack dump:

lua: ../tl//tl.lua:5436: attempt to index a nil value (local 't')
stack traceback:
        ../tl//tl.lua:5436: in upvalue 'resolve'
        ../tl//tl.lua:5517: in local 'resolve'
        ../tl//tl.lua:5554: in upvalue 'resolve_typevars'
        ../tl//tl.lua:5956: in upvalue 'resolve_typevars_at'
        ../tl//tl.lua:5977: in upvalue 'match_typevals'
        ../tl//tl.lua:6007: in upvalue 'resolve_nominal'
        ../tl//tl.lua:6955: in upvalue 'resolve_tuple_and_nominal'
        ../tl//tl.lua:8562: in local 'cbkind_after'
        ../tl//tl.lua:3302: in upvalue 'recurse'
        ../tl//tl.lua:3116: in local 'fn'
        ...     (skipping 19 levels)
        ../tl//tl.lua:3293: in upvalue 'recurse'
        ../tl//tl.lua:3226: in local 'fn'
        ../tl//tl.lua:3293: in upvalue 'recurse'
        ../tl//tl.lua:3116: in local 'fn'
        ../tl//tl.lua:3293: in function <../tl//tl.lua:3273>
        (...tail calls...)
        ../tl//tl.lua:9010: in function 'tl.type_check'
        ../tl//tl.lua:9426: in function <../tl//tl.lua:9408>
        [C]: in function 'require'
        main.tl:2: in main chunk
        (...tail calls...)
        ../tl/tl:1332: in main chunk
        [C]: in ?
hishamhm commented 3 years ago

@jparoz Thank you for the detailed report! This should be now fixed in master!

jparoz commented 3 years ago

Thank you for the prompt help! Very excited to continue exploring Teal.