teal-language / tl

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

[nil] union type does not specialize with and-or idiom #776

Open hishamhm opened 1 month ago

hishamhm commented 1 month ago
do
   local record vers
      record NestedVersion
         string: string
      end
   end

   local type AliasVersion = vers.NestedVersion

   local cv: AliasVersion | string
   local a = cv is vers.NestedVersion and cv.string or cv
   local b = cv is AliasVersion and cv.string or cv
end

do
   local record NotNestedVersion
      string: string
   end

   local cv: NotNestedVersion | string
   local a = cv is NotNestedVersion and cv.string or cv
end

Local variables are not being inferred to string, even though both sides of the and-or "ternary" resolve to string.

hishamhm commented 2 weeks ago

Local variables are not being inferred to string, even though both sides of the and-or "ternary" resolve to string.

This is not true. Consider the case where cv is a record, but cv.string resolves to nil:

   local cv: AliasVersion | string = {}
   local a = cv is vers.NestedVersion and cv.string or cv
   local b = cv is AliasVersion and cv.string or cv

   print(type(a)) --> "table"
   print(type(b)) --> "table"

This can only be solved when nil is handled separately from other types. If we can guarantee that cv.string is a non-nil string, then we'd know for a fact that all types other than nil and boolean are always truthy, and then we could propagate the inference confidently.