Delete papers directory

The directory was moved to https://github.com/luau-lang/research

See https://github.com/Roblox/luau/issues/1074 for context
This commit is contained in:
Arseny Kapoulkine 2023-10-23 09:02:08 -07:00 committed by GitHub
parent d70a02a2d0
commit 13e3af2724
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 0 additions and 1596 deletions

12
papers/.gitignore vendored
View File

@ -1,12 +0,0 @@
*.aux
*.bbl
*.blg
*.dvi
*.fdb_latexmk
*.fls
*.log
*.out
*.xcp
*.nav
*.snm
*.toc

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

View File

@ -1,45 +0,0 @@
# HATRA 21 position paper
A position paper on Luau for [Human Aspects of Types and Reasoning Assistants](https://2021.splashcon.org/home/hatra-2021) (HATRA) 2021.
## Installing latexmk
First install basictex
```
sudo brew install basictex
```
Then install the dependencies for the paper (sigh, by hand):
```
sudo tlmgr update --all
sudo tlmgr install acmart
sudo tlmgr install iftex
sudo tlmgr install xstring
sudo tlmgr install environ
sudo tlmgr install totpages
sudo tlmgr install trimspaces
sudo tlmgr install manyfoot
sudo tlmgr install ncctools
sudo tlmgr install comment
sudo tlmgr install balance
sudo tlmgr install preprint
sudo tlmgr install libertine
sudo tlmgr install inconsolata
sudo tlmgr install newtx
sudo tlmgr install latexmk
sudo tlmgr install montserrat
sudo tlmgr install ly1
```
## Building the paper
To build the paper:
```
latexmk --pdf hatra21
```
To run latexmk in watching mode (where it rebuilds the PDF on each change):
```
latexmk --pdf --pvc hatra21
```

View File

@ -1,177 +0,0 @@
@Misc{Roblox,
author = {Roblox},
title = {What is {Roblox}},
year = 2021,
url = {https://corp.roblox.com},
}
@Misc{Luau,
author = {Roblox},
title = {The {Luau} Programming Language},
year = 2021,
url = {https://luau-lang.org},
}
@Misc{Lua,
author = {Lua.org and {PUC}-Rio},
title = {The {Lua} Programming Language},
year = 2021,
url = {https://lua.org},
}
@Misc{AllEducators,
author = {Roblox},
title = {Roblox Education: All Educators},
year = {2021},
url = {https://education.roblox.com/en-us/educators},
}
@Misc{RobloxDevelopers,
author = {Roblox},
title = {Roblox Developers Expected to Earn Over \$250 Million in 2020; Platform Now Has Over 150 Million Monthly Active Users
},
year = {2020},
url = {https://corp.roblox.com/2020/07/roblox-developers-expected-earn-250-million-2020-platform-now-150-million-monthly-active-users/},
}
@Book{TAPL,
author = {Benjamin C. Pierce},
title = {Types and Programming Languages},
publisher = {{MIT} Press},
year = {2002},
isbn = {0-262-16209-1},
}
@Book{TDDIdris,
author = {Edwin Brady},
title = {Type-Driven Development with {Idris}},
publisher = {Manning},
year = {2017},
isbn = {9781617293023},
}
@PhdThesis{TopQuality,
author = {Bastiaan J. Heeren},
title = {Top Quality Type Error Messages},
school = {U. Utrecht},
year = {2005},
}
@PhdThesis{RepairingTypeErrors,
author = {Bruce J. McAdam},
title = {Repairing Type Errors in Functional Programs},
school = {U. Edinburgh},
year = {2002},
}
@InProceedings{GradualTyping,
author = {Jeremy G. Siek and Walid Taha},
title = {Gradual Typing for Functional Languages},
booktitle = {Proc. Scheme and Functional Programming Workshop},
year = {2006},
pages = {81-92},
}
@InProceedings{WellTyped,
author = {Philip Wadler and Robert B. Findler},
title = {Well-typed Programs Cant be Blamed},
booktitle = {Proc. European Symp. Programming},
year = {2009},
pages = {1-16},
}
@InProceedings{Contracts,
author = {Robert B. Findler and Matthias Felleisen},
title = {Contracts for Higher-order Functions},
booktitle = {Proc. Int. Conf. Functional Programming},
year = {2002},
pages = {48-59},
}
@inproceedings{SuccessTyping,
author = {Lindahl, Tobias and Sagonas, Konstantinos},
title = {Practical Type Inference Based on Success Typings},
year = {2006},
booktitle = {Proc. Int. Conf. Principles and Practice of Declarative Programming},
pages = {167178},
}
@InProceedings{IncorrectnessLogic,
author = {O'Hearn, Peter W.},
title = {Incorrectness Logic},
year = {2020},
booktitle = {Proc. Symp. Principles of Programming Languages},
articleno = {10},
pages = {1-32},
}
@Misc{HowToDrawAnOwl,
author = {Know Your Meme},
title = {How To Draw An Owl},
year = {2010},
url = {https://knowyourmeme.com/memes/how-to-draw-an-owl},
}
@Misc{RustBook,
author = {Klabnik, Steve and Nichols, Carol and the Rust Community},
title = {The Rust Programming Language},
year = {2021},
url = {https://doc.rust-lang.org/book/},
}
@article{TypeClasses,
author = {Hall, Cordelia V. and Hammond, Kevin and Peyton Jones, Simon L. and Wadler, Philip L.},
title = {Type Classes in Haskell},
year = {1996},
volume = {18},
number = {2},
journal = {ACM Trans. Program. Lang. Syst.},
pages = {109138},
}
@InProceedings{Hazel,
author = {Cyrus Omar and Ian Voysey and Ravi Chugh and Matthew Hammer},
title = {Live Functional Programming with Typed Holes},
booktitle = {Proc. Symp. Principles of Programming Languages},
year = {2019},
pages = {14:1-14:28},
}
@InProceedings{MigratoryTyping,
author = {Sam Tobin-Hochstadt and Matthias Felleisen and Robert Bruce Findler and Matthew Flatt and Ben Greenman and Andrew M. Kent and Vincent St-Amour and T. Stephen Strickland and Asumu Takikawa},
title = {Migratory Typing: Ten Years Later},
booktitle = {Proc. Summit on Advances in Programming Languages},
year = {2017},
}
@InProceedings{LinkingTypes,
author = {Daniel Patterson and Amal Ahmed},
title = {Linking Types for Multi-Language Software: Have Your Cake and Eat It Too},
booktitle = {Proc. Summit on Advances in Programming Languages},
year = {2017},
}
@InProceedings{QuickLook,
author = {Serrano, Alejandro and Hage, Jurriaan and Peyton Jones, Simon and Vytiniotis, Dimitrios},
title = {A quick look at impredicativity},
booktitle = {Proc. Int. Conf. Functional Programming},
year = {2020},
}
@InProceedings{Boehm85,
author = {Partial polymorphic type inference is undecidable},
title = {Hans-J. Boehm},
booktitle = {Proc. Symp. Foundations of Computer Science},
year = {1985},
pages = {339-345},
}
@article{LocalTypeInference,
author = {Pierce, Benjamin C. and Turner, David N.},
title = {Local Type Inference},
year = {2000},
volume = {22},
number = {1},
journal = {ACM Trans. Program. Lang. Syst.},
pages = {144},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

View File

@ -1,446 +0,0 @@
\documentclass[acmsmall]{acmart}
\setcopyright{rightsretained}
\copyrightyear{2021}
\acmYear{2021}
\acmConference[HATRA '21]{Human Aspects of Types and Reasoning Assistants}{October 2021}{Chicago, IL}
\acmBooktitle{HATRA '21: Human Aspects of Types and Reasoning Assistants}
\acmDOI{}
\acmISBN{}
\expandafter\def\csname @copyrightpermission\endcsname{\raisebox{-1ex}{\includegraphics[height=3.5ex]{cc-by}} This work is licensed under a Creative Commons Attribution 4.0 International License.}
\expandafter\def\csname @copyrightowner\endcsname{Roblox.}
\newcommand{\squnder}[1]{\color{red}\underline{{\color{black}#1}}\color{black}}
\newcommand{\infer}[2]{\frac{\textstyle#1}{\textstyle#2}}
\newcommand{\erase}{\mathrm{erase}}
\newcommand{\evCtx}{\mathcal{E}}
\newcommand{\NIL}{\mathsf{nil}}
\newcommand{\ANY}{\mathsf{any}}
\newcommand{\TRUE}{\mathsf{true}}
\newcommand{\FALSE}{\mathsf{false}}
\newcommand{\NUMBER}{\mathsf{number}}
\newcommand{\STRING}{\mathsf{string}}
\newcommand{\ERROR}{\mathsf{error}}
\newcommand{\IF}{\mathsf{if}\,}
\newcommand{\LOCAL}{\mathsf{local}\,}
\newcommand{\THEN}{\,\mathsf{then}\,}
\newcommand{\ELSE}{\,\mathsf{else}\,}
\newcommand{\END}{\,\mathsf{end}}
\newcommand{\FUNCTION}{\mathsf{function}\,}
\newcommand{\RETURN}{\mathsf{return}\,}
\newcommand{\FIND}{\mathsf{find}}
\newcommand{\PRINT}{\mathsf{print}}
\newcommand{\strlit}[1]{\mbox{``#1''}}
\begin{document}
\title{Position Paper: Goals of the Luau Type System}
\author{Lily Brown}
\author{Andy Friesen}
\author{Alan Jeffrey}
\affiliation{
\institution{Roblox}
\city{San Mateo}
\state{CA}
\country{USA}
}
\begin{abstract}
Luau is the scripting language that powers user-generated experiences on the
Roblox platform. It is a statically-typed language, based on the
dynamically-typed Lua language, with type inference. These types are used for providing
editor assistance in Roblox Studio, the IDE for authoring Roblox experiences.
Due to Roblox's uniquely heterogeneous developer community, Luau must operate
in a somewhat different fashion than a traditional statically-typed language.
In this paper, we describe some of the goals of the Luau type system,
focusing on where the goals differ from those of other type systems.
\end{abstract}
\maketitle
\section{Introduction}
The Roblox platform allows anyone to create shared,
immersive, 3D experiences. As of July 2021, there are
approximately 20~million experiences available on Roblox, created
by 8~million developers~\cite{Roblox}. Roblox creators are often young: there are
over 200~Roblox kids' coding camps in 65~countries
listed by the company as education resources~\cite{AllEducators}.
The Luau programming language~\cite{Luau} is the scripting language
used by creators of Roblox experiences. Luau is derived from the Lua
programming language~\cite{Lua}, with additional capabilities,
including a type inference engine.
This paper will discuss some of the goals of the Luau type system, such
as supporting goal-driven learning, non-strict typing semantics, and
mixing strict and non-strict types. Particular focus is placed on how
these goals differ from traditional type systems' goals.
\section{Needs of the Roblox platform}
\subsection{Heterogeneous developer community}
Need: \emph{a language that is powerful enough to support professional users, yet accessible to beginners}
Quoting a Roblox 2020 report \cite{RobloxDevelopers}:
\begin{itemize}
\item \emph{Adopt Me!} now has over 10 billion plays and surpassed 1.6 million concurrent users earlier this year.
\item \emph{Piggy}, launched in January 2020, has close to 5 billion visits in just over six months.
\item There are now 345,000 developers on the platform who are monetizing their games.
\end{itemize}
This demonstrates the heterogeneity of the Roblox developer community:
developers of experiences with billions of plays are on the same
platform as children first learning to code. Both of these groups are important to
support: the professional development studios bring high-quality experiences to the
platform, and the beginning creators contribute to the energetic creative community,
forming the next generation of developers.
\subsection{Goal-driven learning}
Need: \emph{organic learning for achieving specific goals}
All developers are goal-driven, but this is especially true for
learners. A learner will download Roblox Studio
(the creation environment for the Roblox platform) with an
experience in mind, such as designing an obstacle course
to play in with their friends.
The user experience of developing a Roblox experience is primarily a
3D interactive one, seen in Fig.~\ref{fig:studio}(a). The user designs
and deploys 3D assets such as terrain, parts and joints, providing
them with physics attributes such as mass and orientation. The user
can interact with the experience in Studio, and deploy it to a Roblox
server so anyone with the Roblox app can play it. Physics, rendering
and multiplayer are all immediately accessible to creators.
\begin{figure}
\includegraphics[width=0.48\textwidth]{studio-mow.png}
\includegraphics[width=0.48\textwidth]{studio-script-editor.png}
\caption{Roblox Studio's 3D environment editor (a), and script editor (b)}
\label{fig:studio}
\end{figure}
At some point during experience design, the experience creator has a need
that can't be met by the game engine alone, such as ``the stairs should
light up when a player walks on them'' or ``a firework is set off
every few seconds''. At this point, they will discover the script
editor, seen in Fig.~\ref{fig:studio}(b).
This onboarding experience is different from many initial exposures to
programming, in that by the time the user first opens the script
editor, they have already built much of their creation, and have a
very specific concrete aim. As such, Luau must allow users to perform a
specific task with as much help as possible from tools.
A common workflow for getting started is to Google the task, then
cut-and-paste the resulting code, adapting it as needed. Since this
is so common, backward compatibility of Luau with existing code is
important, even for learners who do not have an existing code base to
maintain.
Type-driven tools are useful to all creators, in as much as they help
them achieve their current goals. For example type-driven
autocomplete, or type-driven API documentation, are of immediate
benefit. Traditional typechecking can be useful, for example for
catching spelling mistakes, but for most goal-driven developers, the
type system should help or get out of the way.
\subsection{Type-driven development}
Need: \emph{a language that supports large-scale codebases and defect detection}
Professional development studios are also goal-directed (though the
goals may be more abstract, such as ``decrease user churn'' or
``improve frame rate'') but have additional needs:
\begin{itemize}
\item \emph{Code planning}:
code spends much of its time in an incomplete state, with holes
that will be filled in later.
\item \emph{Code refactoring}:
code evolves over time, and it is easy for changes to
break previously-held invariants.
\item \emph{Defect detection}:
code has errors, and detecting these at runtime (for example by crash telemetry)
can be expensive and recovery can be time-consuming.
\end{itemize}
Detecting defects ahead-of-time is a traditional goal of type systems,
resulting in an array of techniques for establishing safety results,
surveyed for example in~\cite{TAPL}. Supporting code planning and
refactoring are some of the goals of \emph{type-driven
development}~\cite{TDDIdris} under the slogan ``type, define,
refine''. A common use of type-driven development is renaming a
property, which is achieved by changing the name in one place,
and then fixing the resulting type errors---once the type system stops
reporting errors, the refactoring is complete.
To help support the transition from novice to experienced developer,
types are introduced gradually, through API documentation and type discovery.
Type inference provides many of the benefits of type-driven development
even to creators who are not explicitly providing types.
\section{Goals of the type system}
\subsection{Infallible types}
Goal: \emph{provide type information even for ill-typed or syntactically invalid programs.}
Programs spend much of their time under development in an ill-typed or incomplete state, even if the
final artifact is well-typed. If tools such as autocomplete and API documentation are type-driven,
this means that tooling needs to rely on type information even for ill-typed
or syntactically invalid programs. An analogy is infallible parsers, which perform error recovery and
provide an AST for all input texts, even if they don't adhere to the parser's syntax.
Program analysis can still flag type errors, which may be presented
to the user with red squiggly underlining. Formalizing this, rather
than a judgment
$\Gamma\vdash M:T$, for an input term $M$, there is a judgment
$\Gamma \vdash M \Rightarrow N : T$ where $N$ is an output term
where some subterms are \emph{flagged} as having type errors, written $\squnder{N}$. Write $\erase(N)$
for the result of erasing flaggings: $\erase(\squnder{N}) = \erase(N)$.
For example, in Lua, the $\STRING.\FIND$ function expects two strings, and returns the
offsets for that string:
\[
\STRING.\FIND(\strlit{hello}, \strlit{ell}) \rightarrow (2, 4)
\qquad
\STRING.\FIND(\strlit{world}, \strlit{ell}) \rightarrow (\NIL, \NIL)
\]
and in Luau it has the type:
\[
\STRING.\FIND : (\STRING, \STRING) \rightarrow (\NUMBER?, \NUMBER?)
\]
In a conventional type system, there is no judgment for ill-typed terms
such as $\STRING.\FIND(\strlit{hello}, 37)$ but in an infallible system we flag the error
and approximate the type, for example:
\[
{} \vdash
\STRING.\FIND(\strlit{hello}, 37)
\Rightarrow
\squnder{\STRING.\FIND(\strlit{hello}, 37)}
:
(\NUMBER?, \NUMBER?)
\]
The goal of infallible types is that every term has a typing judgment
given by flagging ill-typed subterms:
\begin{itemize}
\item \emph{Typability}: for every $M$ and $\Gamma$,
there are $N$ and $T$ such that $\Gamma \vdash M \Rightarrow N : T$.
\item \emph{Erasure}: if $\Gamma \vdash M \Rightarrow N : T$
then $\erase(M) = \erase(N)$
\end{itemize}
Some issues raised by infallible types:
\begin{itemize}
\item Which heuristics should be used to provide types for flagged programs? For example, could one
use minimal edit distance to correct for spelling mistakes in field names?
\item How can we avoid cascading type errors, where a developer is
faced with type errors that are artifacts of the heuristics, rather
than genuine errors?
\item How can the goals of an infallible type system be formalized?
\end{itemize}
\emph{Related work}:
there is a large body of work on type error reporting
(see, for example, the survey in~\cite[Ch.~3]{TopQuality})
and on type-directed program repair
(see, for example, the survey in~\cite[Ch.~3]{RepairingTypeErrors}),
but less on type repair.
The closest work is Hazel's~\cite{Hazel} \emph{typed holes}
where $\squnder{N}$ is treated as a partially-filled hole in the program,
though in that work partially-filled holes are not erased at run-time.
Many compilers perform
error recovery during typechecking, but do not provide a semantics
for programs with type errors.
\subsection{Strict types}
Goal: \emph{no false negatives.}
For developers who are interested in defect detection, Luau provides a \emph{strict mode},
which acts much like a traditional, sound, type system. This has the goal of ``no false negatives''
where any possible run-time error is flagged. This is formalized using:
\begin{itemize}
\item \emph{Operational semantics}: a reduction judgment $M \rightarrow N$ on terms.
\item \emph{Values}: a subset of terms representing a successfully completed evaluation.
\end{itemize}
Error states at runtime are represented as stuck states (terms that are not
values but cannot reduce), and showing that no well-typed program is
stuck. This is not true if typing is infallible, but can fairly
straightforwardly be adapted. We extend the operational semantics to flagged terms,
where $M \rightarrow M'$ implies $\squnder{M} \rightarrow \squnder{M'}$, and
for any value $V$ we have $\squnder{V} \rightarrow V$, then show:
\begin{itemize}
\item \emph{Progress}: if ${} \vdash M \Rightarrow N : T$, then either $N \rightarrow N'$ or $N$ is a value or $N$ has a flagged subterm.
\item \emph{Preservation}: if ${} \vdash M \Rightarrow N : T$ and $N \rightarrow N'$ then $M \rightarrow^*M'$ and ${} \vdash M' \Rightarrow N' : T$.
\end{itemize}
For example in typechecking the program:
\[
\LOCAL (i,j) = \STRING.\FIND(x, y);
\IF i \THEN \PRINT(j-i) \END
\]
the interesting case is $i-j$ in a context where $i$ has type
$\NUMBER$ (since it is guarded by the $\IF$) but $j$ has type
$\NUMBER?$. Since subtraction has type $(\NUMBER, \NUMBER) \rightarrow \NUMBER$,
this is a type error, so the relevant typing judgment is:
\[\begin{array}{r@{}l}
x: \STRING, y: \STRING \vdash {}&
(\LOCAL (i,j) = \STRING.\FIND(x, y);
\IF i \THEN \PRINT(j-i) \END) \\
\Rightarrow {}&
(\LOCAL (i,j) = \STRING.\FIND(x, y);
\IF i \THEN \PRINT(\squnder{j-i}) \END)
\end{array}\]
Some issues raised by soundness for infallible types:
\begin{itemize}
\item How should the judgments and their metatheory be set up?
\item How should type inference and generic functions be handled?
\item Is the operational semantics of flagged values
($\squnder{V} \rightarrow V$) the right one?
\end{itemize}
\emph{Related work}: gradual typing and blame analysis, e.g.~\cite{GradualTyping,WellTyped,Contracts}.
The main difference between this approach and that of migratory typing~\cite{MigratoryTyping}
is that (due to backward compatibility with existing Lua) we cannot introduce
extra code during migration.
\subsection{Nonstrict types}
Goal: \emph{no false positives.}
For developers who are not interested in defect detection, type-driven
tools and techniques such as autocomplete, API documentation
and type-driven refactoring are still useful.
For such developers, Luau provides a
\emph{nonstrict mode}, which we hope will eventually be useful for all
developers. This non-strict typing mode is particularly useful when
adopting Luau types in pre-existing code that was not authored with
the type system in mind. Non-strict mode does \emph{not} aim for
soundness, but instead has the goal of ``no false positives``, in the
sense that any flagged code is guaranteed to produce a runtime error
when executed.
Our previous example was, in fact, a false positive since a programmer
can make use of the fact that $\STRING.\FIND(x, y)$ is either $\NIL$
in both results or neither, so if $i$ is non-$\NIL$ then so is $j$.
This is discussed in the English-language documentation but not reflected
in the type. So flagging $(i - j)$ is a false positive.
On the face of it, detecting all errors without false positives is undecidable, since a program such as
$(\IF f() \THEN \ERROR \END)$ will produce a runtime error when $f()$ is
$\TRUE$. Instead we can aim for a weaker property: that all flagged code
is either dead code or will produce an error. Either of these is a
defect, so deserves flagging, even if the tool does not know
which reason applies.
We can formalize this by defining an \emph{evaluation context}
$\evCtx[\bullet]$, and saying $M$ is \emph{incorrectly flagged}
if it is of the form $\evCtx[\squnder{V}]$. We can then define:
\begin{itemize}
\item \emph{Correct flagging}: if ${} \vdash M \Rightarrow N : T$
then $N$ is correctly flagged.
\end{itemize}
Some issues raised by nonstrict types:
\begin{itemize}
\item Will nonstrict types result in errors being flagged in function call sites
rather than definitions?
\item In Luau, ill-typed property update of most tables succeeds
(the property is inserted if it did not exist), and so functions which
update properties cannot be flagged. Can we still provide meaningful
error messages in such cases?
\item Does nonstrict typing require whole program analysis,
to find all the possible types a property might be updated with?
\item The natural formulation of function types in a nonstrict setting
is that of~\cite{SuccessTyping}: if $f: T \rightarrow U$ and $f(V) \rightarrow^* W$
then $V:T$ and $W:U$. This formulation is \emph{covariant} in $T$,
not \emph{contravariant}; what impact does this have?
\end{itemize}
\emph{Related work}: success types~\cite{SuccessTyping} and incorrectness logic~\cite{IncorrectnessLogic}.
\subsection{Mixing types}
Goal: \emph{support mixed strict/nonstrict development}.
Like every active software community, Roblox developers share code
with one another constantly. First- and third-party developers alike
frequently share entire software packages written in Luau. To add to
this, many Roblox experiences are authored by a team. It is therefore
crucial that we offer first-class support for mixing code written in
strict and nonstrict modes.
Some questions raised by mixed-mode types:
\begin{itemize}
\item How much feedback can we offer for a nonstrict script that is
importing strict-mode code?
\item In strict mode, how do we talk about values and types that are
drawn from nonstrict code?
\item How can we combine the goals of strict and nonstrict types?
\item Can we have strict and non-strict mode infer the same types,
only with different flagging?
\item Is strict-mode code sound when it relies on non-strict code,
which has weaker invariants?
\item How can we avoid introducing function wrappers in higher-order code
at the strict/nonstrict boundary?
\end{itemize}
\emph{Related work}: there has been work on interoperability between different type systems,
notably~\cite{LinkingTypes}, but there the overall goals of the systems were similar safety properties.
In our case, the two type systems have different goals.
\subsection{Type inference}
Goal: \emph{infer types to allow gradual adoption of type annotations.}
Since backward compatibility with existing code is important, we have
to provide types for code without explicit annotations. Moreover, we
want to make use of type-directed tools such as autocomplete, so we
cannot adopt the common strategy of treating all untyped variables as
having type $\ANY$. This leads us to type inference.
To make use of type-driven technologies for programs
without explicit type annotations, we use a type inference algorithm.
Since Luau includes System~F, type inference is undecidable~\cite{Boehm85},
but we can still make use of heuristics such as local type inference~\cite{LocalTypeInference}.
It remains to be seen if type inference can satisfy the goals of
strict and non-strict types. The current Luau system
infers different types in the two modes, which is unsatisfactory as it
makes changing mode a non-local breaking change. In addition,
non-strict inference is currently too imprecise to support
type-directed tools such as autocomplete.
Some questions raised by type inference:
\begin{itemize}
\item How many cases in strict mode cannot be inferred by the type inference system? Minimizing
this kind of error is desirable, to make the type system as unobtrusive as possible.
\item Can something like the Rust traits system~\cite{RustBook} or Haskell classes~\cite{TypeClasses} be used to provide types for overloaded operators, without hopelessly confusing learners?
\item Type inference currently infers monotypes for unannotated
functions, in contrast to QuickLook~\cite{QuickLook}, which can infer generic types.
Will this be good enough for idiomatic Luau scripts?
\item Can type inference be used to infer the same types in strict and nonstrict mode, to ease migrating between modes, with the only difference being error reporting?
\end{itemize}
\emph{Related work}: there is a large body of work on type inference, largely summarized in~\cite{TAPL}.
\section{Conclusions}
In this paper, we have presented some of the goals of the Luau type
system, and how they map to the needs of the Roblox creator
community. We have also explored how these goals differ from traditional
type systems, where it is necessary to accommodate the unique needs of
the Roblox platform. We have sketched what a solution might look like;
all that remains is to draw the owl~\cite{HowToDrawAnOwl}.
\bibliographystyle{ACM-Reference-Format} \bibliography{bibliography}
\end{document}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 589 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

View File

@ -1,203 +0,0 @@
\documentclass[aspectratio=169]{beamer}
\usecolortheme{whale}
\setbeamertemplate{navigation symbols}{}
\definecolor{background}{rgb}{0.945,0.941,0.96}
\definecolor{bluish}{rgb}{0.188,0.455,0.863}
\usepackage{montserrat}
\setbeamerfont{frametitle}{size=\Large,series=\bfseries}
\setbeamerfont{title}{size=\Huge,series=\bfseries}
\setbeamerfont{date}{shape=\itshape}
\setbeamercolor{title}{bg=bluish}
\setbeamercolor{frametitle}{bg=bluish}
\setbeamercolor{background canvas}{bg=background}
\setbeamercolor{itemize item}{fg=bluish}
\setbeamercolor{part name}{fg=background}
\setbeamercolor{part title}{bg=bluish}
\setbeamertemplate{footline}[text line]{\hfill\raisebox{5ex}{\insertshorttitle~~~~\insertframenumber/\inserttotalframenumber~~~~\includegraphics[width=5em]{Logo-Roblox-Black-Full.png}}}
\AtBeginPart{{\setbeamertemplate{footline}{}\frame{\partpage}}}
\newcommand{\erase}{\mathsf{erase}}
\title{Goals of the Luau~Type~System}
\author{Lily Brown \and Andy Friesen \and Alan Jeffrey}
\institute[Roblox]{\includegraphics[width=15em]{Logo-Roblox-Black-Full.png}}
\date[HATRA '21]{\textit{Human Aspects of Types and Reasoning Assistants} 2021}
\begin{document}
{\setbeamertemplate{footline}{}\frame{\titlepage}}
\part{Creator Goals}
\begin{frame}
\frametitle{Roblox}
A platform for creating shared immersive 3D experiences:
\begin{itemize}
\item \textbf{Many}: 20 million experiences, 8 million creators.
\item \textbf{At scale}: e.g.~\emph{Adopt Me!} has 10 billion plays.
\item \textbf{Learners}: e.g.~200+ kids' coding camps in 65+ countries.
\item \textbf{Professional}: 345k creators monetizing experiences.
\end{itemize}
A very heterogeneous community.
\end{frame}
\begin{frame}
\frametitle{Roblox developer community}
All developers are important:
\begin{itemize}
\item \textbf{Learners}: energetic creative community.
\item \textbf{Professionals}: high-quality experiences.
\item \textbf{Everyone inbetween}: some learners become professionals!
\end{itemize}
Satisfying everyone is sometimes challenging.
\end{frame}
\begin{frame}
\frametitle{Roblox Studio}
Demo time!
\end{frame}
\begin{frame}
\frametitle{Learners have immediate goals}
E.g. ``when a player steps on the button, advance the slide''.
\begin{itemize}
\item \textbf{3D scene editor} meets most goals, e.g.~model parts.
\item \textbf{Programming} is needed for reacting to events, e.g.~collisions.
\item \textbf{Onboarding} is very different from ``let's learn to program''.
\item \textbf{Google Stack Overflow} is a common workflow.
\item \textbf{Type-driven tools} are useful, e.g.~autocomplete or API help.
\item \textbf{Type errors} may be useful (e.g.~catching typos) but some are not.
\end{itemize}
Type systems should help or get out of the way.
\end{frame}
\begin{frame}
\frametitle{Professionals have long-term goals}
E.g. ``decrease user churn'' or ``improve frame rate''.
\begin{itemize}
\item \textbf{Code planning}: programs are incomplete.
\item \textbf{Code refactoring}: programs change.
\item \textbf{Defect detection}: programs have bugs.
\end{itemize}
Type-driven development is a useful technique!
\end{frame}
\part{Luau Type System}
\begin{frame}
\frametitle{Infallible types}
Goal: \emph{support type-driven tools (e.g. autocomplete) for all programs.}
\begin{itemize}
\item \textbf{Traditional typing judgment} says nothing about ill-typed terms.
\item \textbf{Infallible judgment}: every term gets a type.
\item \textbf{Flag type errors}: elaboration introduces \emph{flagged} subterms.
\end{itemize}
\emph{Related work}:
\begin{itemize}
\item Type error reporting, program repair.
\item Typed holes (e.g. in Hazel).
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Strict types}
Goal: \emph{no false negatives}.
\begin{itemize}
\item \textbf{Strict mode} enabled by developers who want defect detection.
\item \textbf{Business as usual} soundness via progress + preservation.
\item \textbf{Gradual types} for programs with flagged type errors.
\end{itemize}
\emph{Related work}:
\begin{itemize}
\item Lots and lots for type safety.
\item Gradual typing, blame analysis, migratory types\dots
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Nonstrict types}
Goal: \emph{no false positives}.
\begin{itemize}
\item \textbf{Nonstrict mode} enabled by developers who want type-drive tools.
\item \textbf{Victory condition} does not have an obvious definition!
\item \textbf{A shot at it}: a program is \emph{incorrectly flagged} if it contains
a flagged value (i.e.~a flagged program has successfully terminated).
\item \textbf{Progress + correct flagging} is what we want???
\end{itemize}
\emph{Related work}:
\begin{itemize}
\item Success types (e.g. Erlang Dialyzer).
\item Incorrectness Logic.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Mixing types}
Goal: \emph{support mixed strict/nonstrict development}.
\begin{itemize}
\item \textbf{Per-module} strict/nonstrict mode.
\item \textbf{Combined} progress + preservation with progress + correct flagging?
\end{itemize}
\emph{Related work}:
\begin{itemize}
\item Some on mixed languages, but with shared safety properties.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Type inference}
Goal: \emph{provide benefits of type-directed tools to everyone}.
\begin{itemize}
\item \textbf{Infer types} for all variables. Resist the urge to give up and ascribe a top type when an error is encountered.
\item \textbf{System F} is in Luau, so everything is undecidable. Yay heuristics!
\item \textbf{Different modes} currently infer different types. Boo!
\end{itemize}
\emph{Related work}:
\begin{itemize}
\item Lots, though not on mixed modes.
\end{itemize}
\end{frame}
\part{Thank you!\\Roblox is hiring!}
\end{document}

View File

@ -1,69 +0,0 @@
@InProceedings{BFJ21:GoalsLuau,
author = {L. Brown and A. Friesen and A. S. A. Jeffrey},
title = {Position Paper: Goals of the Luau Type System},
booktitle = {Proc. Human Aspects of Types and Reasoning Assistants},
year = {2021},
url = {https://asaj.org/papers/hatra21.pdf},
}
@Misc{Roblox,
author = {Roblox},
title = {Reimagining the way people come together},
year = 2023,
url = {https://corp.roblox.com},
}
@Misc{Luau,
author = {Roblox},
title = {The {Luau} Programming Language},
year = 2023,
url = {https://luau-lang.org},
}
@Misc{Lua,
author = {Lua.org and {PUC}-Rio},
title = {The {Lua} Programming Language},
year = 2023,
url = {https://lua.org},
}
@Misc{Jef22:SemanticSubtyping,
author = {A. S. A. Jeffrey},
title = {Semantic Subtyping in Luau},
howpublished = {Roblox Technical Blog},
year = {2022},
url = {https://blog.roblox.com/2022/11/semantic-subtyping-luau/},
}
@InProceedings{GF05:GentleIntroduction,
author = {G. Castagna and A. Frisch},
title = {A Gentle Introduction to Semantic Subtyping},
booktitle = {Proc. Principles and Practice of Declarative Programming},
year = {2005},
}
@InProceedings{ST07:GradualTyping,
author = {J. G. Siek and W. Taha},
title = {Gradual Typing for Objects},
booktitle = {Proc. European Conf Object-Oriented Programming},
year = {2007},
pages = {2-27},
}
@Misc{BJ23:agda-typeck,
author = {L. Brown and A. S. A. Jeffrey},
title = {Luau Prototype Typechecker},
year = {2023},
OPTnote = {},
url = {https://github.com/luau-lang/agda-typeck}
}
@article{PT00:LocalTypeInference,
author = {Pierce, B. C. and Turner, D. N.},
title = {Local Type Inference},
year = {2000},
volume = {22},
number = {1},
journal = {ACM Trans. Program. Lang. Syst.},
pages = {144},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

View File

@ -1,156 +0,0 @@
\documentclass[acmsmall]{acmart}
\setcopyright{rightsretained}
\copyrightyear{2023}
\acmYear{2023}
\acmConference[HATRA '23]{Human Aspects of Types and Reasoning Assistants}{October 2023}{Portugal, Spain}
\acmBooktitle{HATRA '23: Human Aspects of Types and Reasoning Assistants}
\acmDOI{}
\acmISBN{}
\expandafter\def\csname @copyrightpermission\endcsname{\raisebox{-1ex}{\includegraphics[height=3.5ex]{cc-by}} This work is licensed under a Creative Commons Attribution 4.0 International License.}
\expandafter\def\csname @copyrightowner\endcsname{Roblox.}
\newcommand{\ANY}{\mathtt{any}}
\newcommand{\ERROR}{\mathtt{error}}
\newcommand{\NUMBER}{\mathtt{number}}
\begin{document}
\title{Goals of the Luau Type System, Two Years On}
\author{Lily Brown}
\author{Andy Friesen}
\author{Alan Jeffrey}
\affiliation{
\institution{Roblox}
\city{San Mateo}
\state{CA}
\country{USA}
}
\begin{abstract}
In HATRA 2021, we presented \emph{The Goals Of The Luau Type System},
describing the human factors of a type system for a
language with a heterogeneous developer community. In this extended
abstract we provide a progress report, focusing on
the unexpected aspects: semantic subtyping and type error
suppression.
\end{abstract}
\maketitle
\section{Recap}
Luau~\cite{Luau} is the scripting language used by the
Roblox~\cite{Roblox} platform for shared immersive experiences. Luau extends
the Lua~\cite{Lua} language, notably by providing type-driven tooling
such as autocomplete and API documentation (as well as traditional type
error reporting). Roblox has hundreds of millions of users, and
millions of creators, ranging from children learning to program for
the first time to professional development studios.
In HATRA 2021, we presented a position paper on the \emph{Goals Of The Luau Type
System}~\cite{BFJ21:GoalsLuau}, describing the human factors issues
with designing a type system for a language with a heterogeneous
developer community. The design flows from the needs of the different
communities: beginners are focused on immediate goals (``the stairs
should light up when a player walks on them'') and less on the code
quality concerns of more experienced developers; for all users
type-driven tooling is important for productivity. These needs result in a design with two modes:
\begin{itemize}
\item \emph{non-strict mode}, aimed at non-professionals, focused on
minimizing false positives (that is, in non-strict mode, any program with a type error has a defect), and
\item \emph{strict mode}, aimed at professionals, focused on
minimizing false negatives (that is, in strict mode, any program with a defect has a type error).
\end{itemize}
%% For both communities, type-driven tooling is important, so we
%% provide \emph{infallible type inference}, which infers types
%% even for ill-typed or syntactically invalid programs.
\section{Progress}
In the two years since the position paper, we have been making changes
to the Luau type system to achieve the goals we set out. Most of the
changes were straightforward, but two were large changes in how we
thought about the design of the type system: replacing the existing
syntactic subtyping algorithm by \emph{semantic subtyping}, and
treating gradual typing as \emph{type error suppression}.
Semantic subtyping
interprets types as sets of values, and subtyping as set
inclusion~\cite{GF05:GentleIntroduction}. This is aligned with the
\emph{minimize false positives} goal of Luau non-strict mode, since
semantic subtyping only reports a failure of subtyping when there is a
value which inhabits the candidate subtype, but not the candidate
supertype.
For example, the program:
\begin{verbatim}
local x : CFrame = CFrame.new()
local y : Vector3 | CFrame
if math.random() < 0.5 then y = CFrame.new() else y = Vector3.new() end
local z : Vector3 | CFrame = x * y
\end{verbatim}
cannot produce a run-time error, since multiplication of \verb|CFrame|s is overloaded:
\begin{verbatim}
((CFrame, CFrame) -> CFrame) & ((CFrame, Vector3) -> Vector3)
\end{verbatim}
In order to typecheck this program, we check that that type is a subtype of:
\begin{verbatim}
(CFrame, Vector3 | CFrame) -> (Vector3 | CFrame)
\end{verbatim}
In the previous, syntax-driven, implementation of subtyping, this subtype check would fail, resulting in a false positive.
We have now released an implementation of semantic subtyping, which does not suffer from this defect.
See our technical blog for more details~\cite{Jef22:SemanticSubtyping}.
Rather than the gradual typing approach
of Siek and Taha~\cite{ST07:GradualTyping}, which uses \emph{consistent
subtyping} where $\ANY \lesssim T \lesssim \ANY$ for any type $T$, we
adopt an approach based on \emph{error suppression}, where $\ANY$ is
an error-suppressing type, and any failures of subtyping involving
error-suppressing types are not reported. Users can explicitly
suppress type errors by declaring variables with type $\ANY$, and
since an expression with a type error has an error-suppressing type we
avoid cascading errors.
We do this by defining a \emph{infallible} typing judgment $\Gamma \vdash M : T$
such that for any $\Gamma$ and $M$, there is a $T$ such that $\Gamma \vdash M : T$.
For example the rule for addition (ignoring overloads for simplicity) is:
\[
\frac{\Gamma \vdash M : T \quad \Gamma \vdash M : U}{\Gamma \vdash M+N : \NUMBER}
\]
We define which judgments produce warnings, for example that rule produces a warning
when
\begin{itemize}
\item either $T \not<: \NUMBER$ and $T$ is not error-suppressing,
\item or $U \not<: \NUMBER$ and $U$ is not error-suppressing.
\end{itemize}
To retain type soundness (in the absence of user-supplied error-suppressing types)
we show that
if $\Gamma \vdash M : T$ and $T$ is error-suppressing, then either
\begin{itemize}
\item $\Gamma$ or $M$ contains an error-suppressing type, or
\item $\Gamma \vdash M : T$ produces a warning.
\end{itemize}
From this it is straightforward to show the usual ``well typed
programs don't go wrong'' type soundness result for programs without explicit
error-suppressing types~\cite{BJ23:agda-typeck}.
\section{Further work}
Currently the type inference system uses greedy inference, which is
very sensitive to order of declarations, and can easily result in
false positives. We plan to replace this by some form of local type
inference~\cite{PT00:LocalTypeInference}.
Currently, non-strict mode operates in the style of gradual type
systems by inferring $\ANY$ as the type for local variables. This does
not play well with type-directed tooling, for example $\ANY$ cannot
provide autocomplete suggestions. Local type inference will infer more
precise union types, and hence better type-driven tooling.
At some point, we hope that error suppression will be the only difference
between strict mode and non-strict mode.
\bibliographystyle{ACM-Reference-Format} \bibliography{bibliography}
\end{document}

View File

@ -1,122 +0,0 @@
@InProceedings{BFJ21:GoalsLuau,
author = {L. Brown and A. Friesen and A. S. A. Jeffrey},
title = {Position Paper: Goals of the Luau Type System},
booktitle = {Proc. Human Aspects of Types and Reasoning Assistants},
year = {2021},
url = {https://asaj.org/papers/hatra21.pdf},
}
@Misc{Roblox,
author = {Roblox},
title = {Reimagining the way people come together},
year = 2023,
url = {https://corp.roblox.com},
}
@Misc{Luau,
author = {Roblox},
title = {The {Luau} Programming Language},
year = 2023,
url = {https://luau-lang.org},
}
@Misc{Lua,
author = {Lua.org and {PUC}-Rio},
title = {The {Lua} Programming Language},
year = 2023,
url = {https://lua.org},
}
@Misc{Jef22:SemanticSubtyping,
author = {A. S. A. Jeffrey},
title = {Semantic Subtyping in Luau},
howpublished = {Roblox Technical Blog},
year = {2022},
url = {https://blog.roblox.com/2022/11/semantic-subtyping-luau/},
}
@InProceedings{GF05:GentleIntroduction,
author = {G. Castagna and A. Frisch},
title = {A Gentle Introduction to Semantic Subtyping},
booktitle = {Proc. Principles and Practice of Declarative Programming},
year = {2005},
}
@InProceedings{ST07:GradualTyping,
author = {J. G. Siek and W. Taha},
title = {Gradual Typing for Objects},
booktitle = {Proc. European Conf Object-Oriented Programming},
year = {2007},
pages = {2-27},
}
@Misc{BJ23:agda-typeck,
author = {L. Brown and A. S. A. Jeffrey},
title = {Luau Prototype Typechecker},
year = {2023},
OPTnote = {},
url = {https://github.com/luau-lang/agda-typeck}
}
@article{PT00:LocalTypeInference,
author = {Pierce, B. C. and Turner, D. N.},
title = {Local Type Inference},
year = {2000},
volume = {22},
number = {1},
journal = {ACM Trans. Program. Lang. Syst.},
pages = {144},
}
@inproceedings{SuccessTyping,
author = {Lindahl, T. and Sagonas, K.},
title = {Practical Type Inference Based on Success Typings},
year = {2006},
booktitle = {Proc. Int. Conf. Principles and Practice of Declarative Programming},
pages = {167178},
}
@InProceedings{Dialyzer,
author="Lindahl, T. and Sagonas, K.",
title="Detecting Software Defects in Telecom Applications Through Lightweight Static Analysis: A War Story",
booktitle="Proc. Asian Symp. Programming Languages and Systems",
year="2004",
pages="91--106",
}
@Misc{NewNonStrictRFC,
author = {A. S. A. Jeffrey},
title = {{RFC} For New Non-strict Mode},
howpublished = {Luau Request For Comment},
year = {2023},
note = {\url{https://github.com/Roblox/luau/pull/1037}},
}
@Inbook{Nielson1999,
author="Nielson, F.
and Nielson, H. R.",
title="Type and Effect Systems",
bookTitle="Correct System Design: Recent Insights and Advances",
year="1999",
publisher="Springer",
pages="114--136",
isbn="978-3-540-48092-1",
}
@Misc{DesignElixir,
author = {G. Castagna and G. Duboc and J. Valim},
title = {The Design Principles of the {Elixir} Type System},
year = {2023},
note = {\url{https://doi.org/10.48550/arXiv.2306.06391}},
}
@article{BidirectionalTyping,
author = {Dunfield, J. and Krishnaswami, N.},
title = {Bidirectional Typing},
year = {2022},
volume = {54},
number = {5},
journal = {ACM Comput. Surv.},
articleno = {98},
numpages = {38},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,366 +0,0 @@
\documentclass[sigplan]{acmart}
\setcopyright{rightsretained}
\copyrightyear{2024}
\acmYear{2024}
\acmConference[Incorrectness '24]{Formal Methods for Incorrectness}{January 2024}{London, UK}
\acmBooktitle{Incorrectness '24: Formal Methods for Incorrectness}
\acmDOI{}
\acmISBN{}
\expandafter\def\csname @copyrightpermission\endcsname{\raisebox{-2ex}{\includegraphics[width=.2\linewidth]{cc-by}} \parbox{.7\linewidth}{\raggedright This work is licensed under a Creative Commons Attribution 4.0 International License.}}
\expandafter\def\csname @copyrightowner\endcsname{Roblox.}
\newcommand{\infer}[2]{\frac{\displaystyle\begin{array}{@{}l@{}}#1\end{array}}{\displaystyle#2}}
\newcommand{\LOCAL}{\mathop{\mathsf{local}}}
\newcommand{\FUNCTION}{\mathop{\mathsf{function}}}
\newcommand{\IF}{\mathop{\mathsf{if}}}
\newcommand{\THEN}{\mathbin{\mathsf{then}}}
\newcommand{\ELSE}{\mathbin{\mathsf{else}}}
\newcommand{\END}{\mathop{\mathsf{end}}}
\newcommand{\NEVER}{\mathsf{never}}
\newcommand{\ERROR}{\mathsf{error}}
\newcommand{\UNKNOWN}{\mathsf{unknown}}
\newcommand{\STRING}{\mathsf{string}}
\newcommand{\NUMBER}{\mathsf{number}}
\newcommand{\MATH}{\mathsf{math}}
\newcommand{\ABS}{\mathsf{abs}}
\newcommand{\LOWER}{\mathsf{lower}}
\newcommand{\fun}{\mathbin{\rightarrow}}
\begin{document}
\title{Towards an Unsound But Complete Type System}
\subtitle{Work In Progress on New Non-Strict Mode for Luau}
\author{Lily Brown}
\author{Andy Friesen}
\author{Alan Jeffrey}
\author{Vighnesh Vijay}
\affiliation{
\institution{Roblox}
\city{San Mateo}
\state{CA}
\country{USA}
}
\begin{abstract}
In HATRA 2021, we presented \emph{The Goals Of The Luau Type System},
describing the human factors of a type system for a language with a
heterogeneous developer community. One of the goals was the design of
type system for bug detection, where we have high confidence that type
errors identify genuine software defects, and that false positives are
minimized. Such a type system is, by necessity, unsound, but we can ask
instead that it is complete. This paper presents a work-in-progress report
on the design and implementation of the new unsound type system for Luau.
\end{abstract}
\maketitle
\section{Introduction}
Luau~\cite{Luau} is the scripting language used by the
Roblox~\cite{Roblox} platform for shared immersive experiences. Luau extends
the Lua~\cite{Lua} language, notably by providing type-driven tooling
such as autocomplete and API documentation (as well as traditional type
error reporting). Roblox has hundreds of millions of users, and
millions of creators, ranging from children learning to program for
the first time to professional development studios.
In HATRA 2021, we presented a position paper on the \emph{Goals Of The Luau Type
System}~\cite{BFJ21:GoalsLuau}, describing the human factors issues
with designing a type system for a language with a heterogeneous
developer community. The design flows from the needs of the different
communities: beginners are focused on immediate goals (``the stairs
should light up when a player walks on them'') and less on the code
quality concerns of more experienced developers; for all users
type-driven tooling is important for productivity. These needs result in a design with two modes:
\begin{itemize}
\item \emph{non-strict mode}, aimed at non-professionals, which
minimizes false positives (that is, in non-strict mode, any program with a type error has a defect), and
\item \emph{strict mode}, aimed at professionals, which
minimizes false negatives (that is, in strict mode, any program with a defect has a type error).
\end{itemize}
The focus of this extended abstract is the design of non-strict mode: what constitutes
a defect, and how can we design a complete type system for detecting them.
(The words ``sound'' and ``complete'' in this sense are far from ideal,
but ``sound type system'' has a well-established meaning, and ``complete''
is well-established as the dual of ``sound'', so here we are.)
The closest work to ours is success typing~\cite{SuccessTyping}, used
in Erlang Dialyzer~\cite{Dialyzer}. The new feature of our work is
that strict and non-strict mode have to interact, whereas Dialyzer only has
the equivalent of non-strict mode.
New non-strict mode is specified in a Luau Request For
Comment~\cite{NewNonStrictRFC}, and is currently being implemented.
We expect it (and other new type checking features) to be available in
2024. This extended abstract is based on the RFC, but written in
``Greek letters and horizontal lines'' rather than ``monospaced text''.
\section{Code defects}
The main goal of non-strict mode is to identify defects, but this requires
deciding what a defect is. Run-time errors are an obvious defect:
\begin{verbatim}
local hi = "hi"
print(math.abs(hi))
\end{verbatim}
but we also want to catch common mistakes such as mis-spelling a property name,
even though Luau returns \verb|nil| for missing property accesses.
For this reason, we consider a larger class of defects:
\begin{itemize}
\item run-time errors,
\item expressions guaranteed to be \verb|nil|, and
\item writing to a table property that is never read.
\end{itemize}
\subsection{Run-time errors}
Run-time errors occur due to run-time type mismatches (such as \verb|5("hi")|)
or incorrect built-in function calls (such as \verb|math.abs("hi")|).
Precisely identifying run-time errors is undecidable, for example:
\begin{verbatim}
if cond() then
math.abs(“hi”)
end
\end{verbatim}
We cannot be sure that this code produces a run-time
error, but we do know that if \verb|math.abs("hi")| is executed, it
will produce an error, so we consider this to be a defect.
\subsection{Expressions guaranteed to be nil}
Luau tables do not error when a missing property is accessed (though embeddings may). So
\begin{verbatim}
local t = { Foo = 5 }
local x = t.Fop
\end{verbatim}
does not produce a run-time error, but is more likely than not a
programmer error. If the programmer intended to
initialize \verb|x| as \verb|nil|, they could have written
\verb|x = nil|. For this reason, we consider it a code defect to use
an expression that the type system infers is of type \verb|nil|, other
than the \verb|nil| literal.
\subsection{Writing properties that are never read}
There is a matching problem with misspelling properties when writing. For example
\begin{verbatim}
function f()
local t = {}
t.Foo = 5
t.Fop = 7
print(t.Foo)
end
\end{verbatim}
does not produce a run-time error, but is more likely than not a
programmer error, since \verb|t.Fop| is written but never read. We can use
read-only and write-only table properties types for this, and consider it an
code defect to create a write-only property.
We have to be careful about this though, because if \verb|f| ended
with \verb|return t|, then it would be a perfectly sensible function
with type \verb|() -> { Foo: number, Fop: number }|. The only way to detect
that \verb|Fop| was never read would be whole-program analysis, which is
prohibitively expensive.
\section{New Non-strict error reporting}
The difficult part of non-strict mode error-reporting is predicting
run-time errors. We do this using an error-reporting
pass that synthesizes a type context $\Delta$ such that if any of the $x : T$ in
$\Delta$ are satisfied, then the program will
produce a type error. For example in the program
\begin{verbatim}
function h(x, y)
math.abs(x)
string.lower(y)
end
\end{verbatim}
an error is reported when \verb|x| isnt a \verb|number|, or \verb|y| isnt a \verb|string|, so the synthesized context is
\begin{verbatim}
x : ~number, y : ~string
\end{verbatim}
(\verb|~T| is Luau's concrete syntax for type negation.)
In:
\begin{verbatim}
function f(x)
math.abs(x)
string.lower(x)
end
\end{verbatim}
an error is reported when \verb|x| isnt a \verb|number| or isnt a \verb|string|, so the context is
\begin{verbatim}
x : ~number | ~string
\end{verbatim}
(\verb"T | U" is Luau's concrete syntax for type union.)
Since the type \verb"~number | ~string" is equivalent to the type \verb|unknown| (which contains every value),
non-strict mode can report a warning, since calling the function is guaranteed to throw a run-time error.
In contrast:
\begin{verbatim}
function g(x)
if cond() then
math.abs(x)
else
string.lower(x)
end
end
\end{verbatim}
synthesizes context
\begin{verbatim}
x : ~number & ~string
\end{verbatim}
(\verb|T & U| is Luau's concrete syntax for type intersection.)
Since \verb|~number & ~string| is not equivalent to \verb|unknown|, non-strict mode reports no warning.
\begin{figure*}
\[\begin{array}{c}
\infer{
\Gamma \vdash M : \NEVER \dashv \Delta_1 \\
\Gamma, x : T \vdash B \dashv \Delta_2, x : U \\
\mbox{(warn if $\UNKNOWN <: U$)}
}{
\Gamma \vdash (\LOCAL x : T = M; B) \dashv (\Delta_1 \cup \Delta_2)
}
\quad
\infer{
\Gamma \vdash M : \NEVER \dashv \Delta_1 \\
\Gamma \vdash B \dashv \Delta_2 \\
\Gamma \vdash C \dashv \Delta_3
}{
\Gamma \vdash (\IF M \THEN B \ELSE C \END) \dashv (\Delta_1 \cup (\Delta_2 \cap \Delta_3))
}
\\[\bigskipamount]
\infer{}{
\Gamma \vdash x : T \dashv (x : T)
}
\quad
\infer{
\mbox{(warn if $k:T$)}
}{
\Gamma \vdash k : T \dashv \emptyset
}
\quad
\infer{
\Gamma, x:S \vdash B \dashv \Delta, x:U \\
\mbox{(warn if $\UNKNOWN <: U$)}\\
\mbox{(warn if ${\FUNCTION} <: T$)}
}{
\Gamma \vdash (\FUNCTION (x : S) B \END) : T \dashv \Delta
}
\quad
\infer{
\Gamma \vdash M : (S \fun \ERROR) \\
\Gamma \vdash M : \neg{\FUNCTION} \dashv \Delta_1 \\
\Gamma \vdash N : S \dashv \Delta_2 \\
\mbox{(warn if $\Gamma \vdash M : (\UNKNOWN \fun (T \cup \ERROR))$)}
}{
\Gamma \vdash M(N) : T \dashv \Delta_1 \cup \Delta_2
}
\end{array}\]
\caption{Type context synthesis for blocks ($\Gamma \vdash B \dashv \Delta$) and expressions ($\Gamma \vdash M:T \dashv \Delta$)}
\label{fig:ctxtgen}
\end{figure*}
\begin{figure*}
\[
\infer{
\begin{array}[b]{c}
\infer{}{\Gamma \vdash \MATH.\ABS : (\neg\NUMBER \fun \ERROR)} \\[\bigskipamount]
\infer{}{\Gamma \vdash \MATH.\ABS : \neg{\FUNCTION} \dashv \emptyset}
\end{array}
\infer{
\Gamma \vdash \STRING.\LOWER : (\neg\STRING \fun \ERROR) \\
\Gamma \vdash \STRING.\LOWER : \neg{\FUNCTION} \dashv \emptyset \\
\Gamma \vdash x : \neg{\STRING} \dashv (x : \neg\STRING) \\
\mbox{(warn since $\Gamma \vdash \STRING.\LOWER : \UNKNOWN \fun (\neg\NUMBER \cup \ERROR)$)}
}{\Gamma \vdash \STRING.\LOWER(x) : \neg{\NUMBER} \dashv (x : \neg\STRING)}
}{\Gamma \vdash (\MATH.\ABS(\STRING.\LOWER(x)) : \NEVER \dashv (x : \neg\STRING)}
\]
\caption{Example warning}
\label{fig:example}
\end{figure*}
In Figure~\ref{fig:ctxtgen} we provide some of the inference rules for
context synthesis, and the warnings that it
produces. These are run after type inference, so they can assume that
all code is fully typed.
In the judgment $\Gamma \vdash M : T \dashv
\Delta$, the type context $\Gamma$ is the usual \emph{checked} type
context and $\Delta$ is the \emph{synthesized} context used to predict
run-time errors (following the terminology of bidirectional
typing~\cite{BidirectionalTyping}).
\begin{conjecture}\label{conj:complete}%
If $\Gamma \vdash M : T \dashv \Delta, x:U$ and $\sigma$ is a closing
substitution where $\sigma(x) : U$ and $M[\sigma] \rightarrow^* v$,
then $v : T$.
\end{conjecture}
\begin{corollary}\label{cor:complete}%
If $\Gamma \vdash M : \NEVER \dashv \Delta, x:\UNKNOWN$ and $\sigma$ is a closing
substitution, then $M[\sigma]$ does not terminate successfully.
\end{corollary}
\section{Checked functions}
The crucial aspect of this type system is that we have a type $\ERROR$
inhabited by no values, and by expressions which may throw a run-time exception.
(This is essentially a very simple type and effect system~\cite{Nielson1999}
with one effect.)
The rule for function application $M(N)$
has two dependencies on the type for $M$:
\[\begin{array}{c}
\Gamma \vdash M : (S \fun \ERROR)
\\[\jot]
\Gamma \vdash M : (\UNKNOWN \fun (T \cup \ERROR))
\end{array}\]
Since Luau is based on semantic subtyping~\cite{GF05:GentleIntroduction,Jef22:SemanticSubtyping} and supports
intersection types, this is equivalent to asking for $M$ to be an
overloaded function, where one overload has argument type $\UNKNOWN$, and
one has result type $\ERROR$. For example:
\[
\MATH.\ABS : (\NUMBER \fun \NUMBER) \cap (\neg\NUMBER \fun \ERROR)
\]
and so (by subsumption):
\[\begin{array}{c}
\MATH.\ABS : (\neg\NUMBER \fun \ERROR)
\\[\jot]
\MATH.\ABS : (\UNKNOWN \fun (\NUMBER \cup \ERROR))
\end{array}\]
This is a common enough idiom it is worth naming it:
we call any function of type
\[
(S \fun T) \cap (\neg S \fun \ERROR)
\]
a \emph{checked} function, since it performs a run-time check
on its argument. They are called \emph{strong arrows}
in Elixir~\cite{DesignElixir}.
Note that this type system has the usual subtyping rule for
functions: contravariant in their argument type, and
covariant in their result type. In contrast, checked functions
are invariant in their argument type, since one overload
$S \fun T$ is contravariant in $S$, and the other $\neg S \fun \ERROR$
is covariant.
This system is also different from success
typings~\cite{SuccessTyping}, which has functions
$(\neg S \fun \ERROR) \cap (\UNKNOWN \fun (T \cup \ERROR))$,
in our system, which are covariant in both $S$ and $T$.
\section{Future work}
This type system is still in the design phase~\cite{NewNonStrictRFC}, though we hope
the implementation will be ready by the end of 2023. This will include
testing the implementation on our unit tests, and on large code bases.
There is an Agda development of a core of strict mode~\cite{BJ23:agda-typeck}. It
should extend to non-strict mode, at which point
Conjecture~\ref{conj:complete} (or something like it)
will be mechanically verified.
\bibliographystyle{ACM-Reference-Format} \bibliography{bibliography}
\end{document}