Skip to content

Scout RFC: is keyword.#204

Open
alexmccord wants to merge 15 commits into
luau-lang:masterfrom
alexmccord:kw-is-cool
Open

Scout RFC: is keyword.#204
alexmccord wants to merge 15 commits into
luau-lang:masterfrom
alexmccord:kw-is-cool

Conversation

@alexmccord
Copy link
Copy Markdown
Contributor

@Ukendio
Copy link
Copy Markdown

Ukendio commented May 11, 2026

I personally want a more powerful feature to introspect types on runtime than this, it seems boring to have yet another way of doing something that can already be done ostensibly + integrating with the class feature. I know the luau team is conflicted with typeof but I really liked it and wish was there was a function that gave more expansive information that is readable on runtime.

What I had in mind was something like this and would aim to solve the same problem while integrating with the existing syntax and has similar ergonomics to user defined type functions

local ti = typeinfo(x)
if ti.type == "class" and t1.name == "Part" then 
  
end
if ti.type == "table" then 
  for k, v in ti.members do 

  end
end
if ti.type == "function" then 
  for k, v in ti.generics then 

  end
  for k, v in ti.parameters then 
  
  end
end

@TenebrisNoctua
Copy link
Copy Markdown

I feel like this RFC could use additional examples in the motivation section. The rest of the RFC is fine, but it could benefit from additional reasons as to why people would rather have is than typeof(...) and :isA().

@alexmccord alexmccord marked this pull request as ready for review May 11, 2026 20:26
@alexmccord alexmccord changed the title is keyword. Scout RFC: is keyword. May 11, 2026
@MagmaBurnsV
Copy link
Copy Markdown
Contributor

I don't know how I feel about adding new syntax with as many surprising restrictions/gotchas as this. I feel even more uncomfortable with the proposed evaluation semantics.

First, is poses the exact same syntax complications that the as keyword did 6 years ago. Disregarding the increased compiler complexity from the arbitrary lookahead required to make this work, the subtle differences with x is T and x is (T) destroys intuition with how expressions are treated in the language, because the rule "you can put explicit parentheses around any associativity and it's the same thing" breaks. Other oddities like x is not T and x is T :: U make the rules even harder to learn because they aren't really consistent.

Second, the typename resolution rules are unhygienic. Making an exception to the "identifiers fallback to the global namespace if not local" rule is bad enough, but I also want to mention that this prevents users from naming their locals anything that collides with a typename, lest they permanently break the expression:

local boolean = true
local result = x is boolean -- impossible to do now, not even forward-declaring an alias can fix this

All of these ugly warts combined convinces me that this is not worth the added syntax sugar.

Comment thread docs/syntax-is-keyword.md
@alexmccord
Copy link
Copy Markdown
Contributor Author

alexmccord commented May 12, 2026

First, is poses the exact same syntax complications that the as keyword did 6 years ago.

It doesn't! This RFC explains this at this section, in particular.

Other oddities like x is not T and x is T :: U make the rules even harder to learn because they aren't really consistent.

This RFC covers this. I already said that these two cannot be used together, and you have to explicitly write parentheses around the expression you want to cast or perform a type test, which is what happens if is and :: has the same precedence, and both are neither left nor right associative. So parentheses are required. I'll rephrase this in the RFC to a little bit clearer.

Second, the typename resolution rules are unhygienic. [sic]

local boolean = true
local result = x is boolean -- impossible to do now, not even forward-declaring an alias can fix this

This is true, but...

  1. Why would you store a value in a local named boolean? It is absolutely not descriptive enough.
  2. Renaming is always available.
  3. The type system will warn you that boolean is not a subtype of class, even in nonstrict mode.
  4. You already can shadow globals quite often. Does that make globals unhygienic? Yes. Yet when you want to use the globals, you end up renaming your locals, as opposed to aliasing the globals. This tells you a lot.

I'll add this into the RFC as a wart, but counter it with it not being all that different from globals. Global typenames are no different from global libraries from this point of view.

@MagmaBurnsV
Copy link
Copy Markdown
Contributor

Would a less magical global is(x, kind) function be an alternative the team would be willing to take? It would work basically the same way, where if you pass in a class/interface value to it, it will do an isinstance check, and if you pass in a string, it routes to a predicate registry defined by the host. Since it's an intrinsic function, type refinement and optimizations are still possible.

This is pretty much exactly what the RFC is proposing, but without the awkward syntax and namespacing rules. I find it surprising that this option isn't even mentioned in the alternatives.

Comment thread docs/syntax-is-keyword.md Outdated
Comment thread docs/syntax-is-keyword.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants