|
| 1 | +# 0.24.0 - Teal Spring '24 |
| 2 | + |
| 3 | +2024-10-07 |
| 4 | + |
| 5 | +This a big release! It is a culmination of work that has spanned multiple |
| 6 | +years, and it would not be possible without the amazing feedback given by |
| 7 | +the community on the `next` branch, where this was developed. This release |
| 8 | +does include that "lot of new code" that I wanted to merge in the "near |
| 9 | +future", as stated in the previous release's changelog. |
| 10 | + |
| 11 | +The main feature is the addition of interfaces, which introduces a model for |
| 12 | +subtyping table types in the language. That should allow for representing the |
| 13 | +various kinds of object models that are used across the Lua ecosystem, without |
| 14 | +promoting any particular class/object system over the others. |
| 15 | + |
| 16 | +This release features commits by François Perrad, Victor Ilchev and Hisham |
| 17 | +Muhammad. |
| 18 | + |
| 19 | +## What's New |
| 20 | + |
| 21 | +### Language |
| 22 | + |
| 23 | +* **Interfaces**: you can now declare abstract interfaces, and record types |
| 24 | + can implement them. This allows you to declare subtyping relations, and |
| 25 | + better support inheritance models (e.g. `local record Circle is Shape`). |
| 26 | + * Records and interfaces may declare a `where` clause with an expression |
| 27 | + over `self`, which allows the `is` operator to discriminate the type. |
| 28 | + * With discriminated record types, it is now possible to declare unions |
| 29 | + over multiple record types. |
| 30 | + * "Arrayrecords" are no longer a distinct type: they are just records |
| 31 | + that implement an array interface (e.g. `local record R is {T}`) |
| 32 | + * Type variables in functions can now have constraints on interfaces |
| 33 | + (e.g. `function my_func<F is MyInterface>(...)`) |
| 34 | + * `self` is now a valid type that can be used when declaring arguments |
| 35 | + in functions declared in interfaces and records |
| 36 | + * When a record is declared to be a subtype of an interface using `is`, |
| 37 | + any function arguments using `self` in the parent interface type will |
| 38 | + then resolve to the child record's type. |
| 39 | +* **Optional/required arguments in function calls** - functions may declare |
| 40 | + arguments as optional, affecting the required arity of function calls. |
| 41 | + The rightmost arguments of a function can have their variable names |
| 42 | + annotated with a `?` sign, indicating that the argument does not need |
| 43 | + to be passed in a function call. This refers only to the presence of the |
| 44 | + argument in a call, and not to its type or nullability: a required |
| 45 | + argument may still be called with an explicit `null`, but an optional |
| 46 | + argument may be elided. |
| 47 | + * In previous versions of Teal, all function arguments were effectively |
| 48 | + optional. This means that Teal is now stricter which checking for |
| 49 | + function calls. You can use `--feat-arity=off` in the command line |
| 50 | + or `feat_arity = "off"` in `tlconfig.lua` to obtain the previous |
| 51 | + behavior. |
| 52 | + * To convert code that uses the old arity checking rules to the new |
| 53 | + behavior, you can also use compiler pragmas in the code, |
| 54 | + `--#pragma arity off` and `--#pragma arity off` to disable or enable |
| 55 | + stricter arity checks. |
| 56 | +* **Macro expressions**: you can declare a restricted form of function called |
| 57 | + a `macroexp`, which is always expanded inline. These can also be used |
| 58 | + to declare compile-time metamethods, which expand without requiring |
| 59 | + a metatable at runtime. The `where` clauses used in interfaces and |
| 60 | + records are syntax sugar for macro expressions that implement a |
| 61 | + pseudo-metamethod `__is`. |
| 62 | +* Dynamic `require` calls that do not take a module name as a literal |
| 63 | + string are now allowed, and return `any`; you can load a static type |
| 64 | + definition using `local type MyType = require("...")` and then cast |
| 65 | + your dynamic require like so: `local my_mod = require(var) as MyType` |
| 66 | +* The type system is more nominal: all named types are now treated nominally, |
| 67 | + except for unions, which are always type aliases. Previously record types |
| 68 | + were nominal, but a named typed that resolved to a primitive such as |
| 69 | + `integer` was structural. There are still subleties on the rules for when |
| 70 | + a `local type` produces a new distinct type or an alias; they are |
| 71 | + [explained in the docs](docs/aliasing.md). |
| 72 | +* The `<total>` attribute for variables can now only be applied when |
| 73 | + initializing variables with literal tables. This is a minor breaking change, |
| 74 | + but the usefulness of this attribute in other cases was very limited, |
| 75 | + and it also produced misleading results. |
| 76 | +* Improved type signatures in the standard library |
| 77 | + * `select` produces variadic returns |
| 78 | + |
| 79 | +### API |
| 80 | + |
| 81 | +* Simplified API in the `tl` module. |
| 82 | + * The 0.15 API is still supported for backwards compatibility. |
| 83 | + |
| 84 | +### Tooling |
| 85 | + |
| 86 | +* `tl build` was removed. [Cyan](https://github.com/teal-language/cyan) |
| 87 | + should be used instead as the build tool for Teal projects. |
| 88 | + |
| 89 | +### Fixes |
| 90 | + |
| 91 | +* Fix commits included in this release refer both to bugs present |
| 92 | + in the `master` branch as well as fixes specific to the 0.24 series, |
| 93 | + reported by the community during the beta testing of this release. |
| 94 | + The Git history and the GitHub issues list contain a more detailed |
| 95 | + accounting of the bugfixes that went into this release. |
| 96 | + Some of the fixes include: |
| 97 | + * `tl check` now reports if the input file does not exist. |
| 98 | + * Reporting location of the end of an `if` block correctly. |
| 99 | + * No longer crash if a `require()` epression fails to resolve (#778). |
| 100 | + * `tl types` now reports the types of variables in `for` loops. |
| 101 | + * Improved error message when calling functions with insufficient |
| 102 | + arguments. |
| 103 | + * Disallowing using a base type as a type variable name. |
| 104 | + * Type arguments resolving correctly in recursive functions. |
| 105 | + * Type arguments resolving correctly in nested records (#754). |
| 106 | + * `or` type inference between types with a subtyping relation |
| 107 | + resolves to whichever is the larger type. |
| 108 | + * Reporting an error if an iterator used in a generic `for` does not |
| 109 | + declare a return value type (#736). |
| 110 | + * When checking `<total>` values, no longer reporting record |
| 111 | + function and metamethods as missing fields (#749). |
| 112 | + * Localizing a record no longer makes the local a type (#759). |
| 113 | + * Bad assignments of record tables are reported (#752). |
| 114 | + * Nominal type alias declarations work as expected (#238). |
| 115 | + * Nominals with generics can be resolved correcty (#777). |
| 116 | + * Nested types are not closed too early (#775). |
| 117 | + * Not failing when resolving nested empty tables. |
| 118 | + * Exporting generics and type aliases from modules correctly |
| 119 | + using `return` at the toplevel (#804). |
| 120 | + |
1 | 121 | # 0.15.3
|
2 | 122 |
|
3 | 123 | 2023-11-05
|
|
0 commit comments