739 lines
32 KiB
Plaintext
739 lines
32 KiB
Plaintext
= Pkl 0.33 Release Notes
|
|
:version: 0.33
|
|
:version-minor: 0.33.0
|
|
:release-date: November 5th, 2026
|
|
:version-next: 0.34
|
|
:version-next-date: February 2027
|
|
|
|
include::partial$intro.adoc[]
|
|
|
|
== Highlights [small]#💖#
|
|
|
|
[[generic-methods]]
|
|
=== Generic Methods
|
|
|
|
Support for generic methods has been greatly expanded (https://github.com/apple/pkl/pull/1849[#1849], https://github.com/apple/pkl/pull/1940[#1940]).
|
|
|
|
A generic method is a method that accepts types as arguments.
|
|
This is a powerful tool that allows writing business logic that works over a variety of types.
|
|
|
|
For example, this code declares two parameters: type parameter `T`, and value parameter `arg`.
|
|
|
|
[source,pkl]
|
|
----
|
|
function identity<T>(arg: T): T = arg
|
|
----
|
|
|
|
Generic methods currently already exist in a limited sense:
|
|
|
|
. Only the standard library can declare generic methods.
|
|
. It is not possible to pass in type arguments when calling generic methods.
|
|
|
|
In Pkl 0.33, both of these restrictions are lifted.
|
|
|
|
To pass type arguments into a generic method, add the type surrounded by angle brackets:
|
|
|
|
[source,pkl]
|
|
----
|
|
result = identity<String>("Hello, World!")
|
|
----
|
|
|
|
If type arguments are omitted entirely, it behaves as calling the method with the `unknown` type.
|
|
The following two are logically identical:
|
|
|
|
[source,pkl]
|
|
----
|
|
result = identity("Hello, World!")
|
|
result2 = identity<unknown>("Hello, World!")
|
|
----
|
|
|
|
This is a <<parser-rule-change-for-comparison,breaking change>>: in some cases, code that parses as a comparison expression now parses as a method call.
|
|
|
|
To read more about generic methods, consult the xref:language-reference:index.adoc#generic-methods[language reference].
|
|
|
|
To learn more about the design of generic method calls, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0032-generic-methods.adoc[SPICE-0032].
|
|
|
|
=== New standard library module: `pkl:net`
|
|
|
|
A new standard library module is introduced called pkldoc:#[pkl:net], for working with network types (https://github.com/apple/pkl/pull/1834[#1834]).
|
|
|
|
Its centerpiece is pkldoc:Url[pkl:net], a URL as defined by https://www.rfc-editor.org/rfc/rfc3986[RFC 3986].
|
|
A string is parsed with pkldoc:#Url()[pkl:net], which accepts an absolute URL as well as a relative reference, and which throws if the string cannot be parsed:
|
|
|
|
[source,pkl]
|
|
----
|
|
import "pkl:net"
|
|
|
|
local url = net.Url("https://user:pw@example.com:8080/a/b c?q=1&q=2#f")
|
|
|
|
scheme = url.scheme // "https"
|
|
rawUserInfo = url.rawUserInfo // "user:pw"
|
|
authority = url.authority // "user:pw@example.com:8080"
|
|
rawHost = url.rawHost // "example.com"
|
|
rawPort = url.rawPort // "8080"
|
|
port = url.port // 8080
|
|
rawPath = url.rawPath // "/a/b%20c"
|
|
path = url.path // "/a/b c"
|
|
pathSegments = url.pathSegments // List("a", "b c")
|
|
rawQuery = url.rawQuery // "q=1&q=2"
|
|
queryParameters = url.queryParameters // Mapping { ["q"] = Listing { "1"; "2" } }
|
|
rawFragment = url.rawFragment // "f"
|
|
----
|
|
|
|
Parsing is lenient: whatever cannot appear literally in a component is percent-encoded as its UTF-8 bytes, and whatever is already encoded is kept as written.
|
|
Every component is held percent-encoded in its `raw` property, whether the input was encoded or not; the percent-decoded form of each is available as `userInfo`, `host`, `path`, `query`, and `fragment`.
|
|
The derived `pathSegments` and `queryParameters` are percent-decoded too.
|
|
|
|
A URL can also be built from its components, or derived from another URL by amending it.
|
|
A component given this way has to be percent-encoded already:
|
|
|
|
[source,pkl]
|
|
----
|
|
built = new net.Url {
|
|
scheme = "https"
|
|
rawHost = "example.com"
|
|
rawPath = "/a%20b"
|
|
}.toString() // "https://example.com/a%20b"
|
|
|
|
local base = net.Url("https://example.com/a?q=1")
|
|
|
|
amended = (base) { rawQuery = null }.toString() // "https://example.com/a"
|
|
----
|
|
|
|
Each component is type-checked, so a URL built this way cannot be malformed.
|
|
For example, a `rawPort` can only hold digits, only a URL with a `rawHost` can have one, and a `rawPath` of `"/a b"` is rejected.
|
|
The decoded components are `fixed`, so they cannot be amended.
|
|
|
|
A relative reference can be resolved against an absolute URL, which also removes dot segments from the result's path:
|
|
|
|
[source,pkl]
|
|
----
|
|
resolved = net.Url("https://example.com/a/b").resolve("../c").toString() // "https://example.com/c"
|
|
----
|
|
|
|
Comparing two URLs with `==` compares their components as written.
|
|
To instead compare them as the *syntax-based normalization* of RFC 3986, where scheme and host are case-insensitive and percent-encoding is normalized, use `equals()`:
|
|
|
|
[source,pkl]
|
|
----
|
|
same = net.Url("HTTPS://Example.com/%7Euser").equals(net.Url("https://example.com/~user")) // true
|
|
----
|
|
|
|
The module also provides standalone helpers: pkldoc:#encodeUrlComponent()[pkl:net] and pkldoc:#decodeUrlComponent()[pkl:net] for percent-encoding, and pkldoc:#buildQuery()[pkl:net] and pkldoc:#parseQuery()[pkl:net] for `application/x-www-form-urlencoded` queries.
|
|
|
|
Alongside this module, `pkl:base` gains pkldoc:String#isValidUrl[], which tells whether a string is a valid absolute URL.
|
|
It is stricter than `net.Url()`, which also parses a relative reference, and which percent-encodes whatever cannot appear literally in a URL component.
|
|
The `Uri` typealias is now defined in terms of it, which is a <<uri-validates,breaking change>>.
|
|
|
|
=== New standard library module: `pkl:syntax`
|
|
|
|
A new standard library module is introduced called pkldoc:#[pkl:syntax], for working with Pkl source code (https://github.com/apple/pkl/pull/1821[#1821], https://github.com/apple/pkl/pull/1964[#1964], https://github.com/apple/pkl/pull/1955[#1955]).
|
|
|
|
It has three parts:
|
|
|
|
* pkldoc:Parser[pkl:syntax] parses a string or resource into a syntax tree, as either a module or an expression.
|
|
* pkldoc:Node[pkl:syntax] is a node of that tree.
|
|
It has a `type`, `children`, the verbatim source `text`, and the source `span`.
|
|
Nodes can be searched, folded, and replaced with the `find*`, `fold`, and `replace*` methods.
|
|
* pkldoc:FormattingRenderer[pkl:syntax] renders a tree back to Pkl source code, using the canonical Pkl formatter.
|
|
|
|
[source,pkl]
|
|
----
|
|
import "pkl:syntax"
|
|
|
|
local myModule = new syntax.Parser {}.parseModule("""
|
|
class Point {
|
|
x: Int
|
|
y: Int
|
|
}
|
|
""")
|
|
|
|
className = myModule.findChild((n) -> n.type == "class").findChildOfType("identifier").text // "Point"
|
|
|
|
ifCount = myModule.fold(0, (acc, n) -> if (n.type == "if_expr") acc + 1 else acc) // 0
|
|
----
|
|
|
|
=== C Library (libpkl)
|
|
|
|
A new C library, libpkl, is introduced (https://github.com/apple/pkl/pull/1238[#1238], https://github.com/apple/pkl/pull/1799[#1799], https://github.com/apple/pkl/pull/1801[#1801], https://github.com/apple/pkl/pull/1805[#1805], https://github.com/apple/pkl/pull/1812[#1812]).
|
|
|
|
One of Pkl's selling points is the ability to embed the language into another runtime as a library.
|
|
However, currently, callers from non-JVM languages must spawn Pkl as a child process.
|
|
This introduces a system dependency on downstream users, and also introduces complexity and overhead for the operating system.
|
|
|
|
To address this pain point, a new library called libpkl is released for the C language.
|
|
|
|
This is a low-level library meant to be called into from language binding libraries.
|
|
It exposes the xref:bindings-specification:message-passing-api.adoc[message passing API] through a small C interface (`pkl.h`).
|
|
|
|
Archives containing the header, both static and dynamic (shared) libraries, and `pkg-config` files are published for each supported OS and architecture, as part of the GitHub release.
|
|
|
|
To read more about libpkl, consult the xref:libpkl:index.adoc[libpkl documentation].
|
|
|
|
To read more about the design of this feature, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0015-c-library-for-pkl.adoc[SPICE-0015].
|
|
|
|
Thank you to https://github.com/KushalP[@KushalP] for their contributions to this feature!
|
|
|
|
=== CPU Profiler
|
|
|
|
The Pkl CLI can now profile where an evaluation spends its CPU time (https://github.com/apple/pkl/pull/1823[#1823], https://github.com/apple/pkl/pull/1931[#1931]).
|
|
|
|
Profiling is enabled by passing `--profile-cpu-output`, which sets the file to write the profile to.
|
|
The profile is written in https://github.com/google/pprof[pprof] format, so it can be explored with any tool that reads it, such as `go tool pprof`.
|
|
|
|
[source,shell,opts=novalidate]
|
|
----
|
|
$ pkl eval --profile-cpu-output profile.pb.gz myConfig.pkl
|
|
$ go tool pprof -http=:8080 profile.pb.gz
|
|
----
|
|
|
|
Profiling is only exposed through the CLI.
|
|
For more details, consult xref:pkl-cli:index.adoc#profile-cpu-output[the CLI documentation].
|
|
|
|
== Noteworthy [small]#🎶#
|
|
|
|
=== `this` as a type
|
|
|
|
The `this` keyword can now be used as a type (https://github.com/apple/pkl/pull/1708[#1708], https://github.com/apple/pkl/pull/1962[#1962]).
|
|
|
|
A self type is the type of the object that a member is accessed on.
|
|
Self types are useful when building class hierarchies, because they let a member refer to the _same_ type as the object it belongs to, even after the class is extended.
|
|
|
|
Currently, Pkl has a self-type, `module`, but it specifically describes the type of the module object.
|
|
There is no equivalent for regular classes nor objects.
|
|
|
|
To address this shortcoming, the `this` keyword is now also a type.
|
|
It refers to the self-type of the directly enclosing object, class, or module.
|
|
|
|
When a class is extended, `this` in an inherited member refers to the subclass, not to the class that declares the member:
|
|
|
|
[source,pkl]
|
|
----
|
|
open class Node {
|
|
parent: this?
|
|
children: List<this>
|
|
}
|
|
|
|
class SpecialNode extends Node {
|
|
special: Boolean
|
|
}
|
|
|
|
node: SpecialNode = new {
|
|
special = true
|
|
parent = new SpecialNode { special = false; children = List() } // <1>
|
|
children = List(new SpecialNode { special = true; children = List() })
|
|
}
|
|
|
|
bad: SpecialNode = new {
|
|
special = true
|
|
parent = new Node {} // <2>
|
|
}
|
|
----
|
|
<1> `parent` has type `SpecialNode?`.
|
|
<2> Error: `Node` is not a `SpecialNode`.
|
|
|
|
The `this` type can be used in properties, method parameters and return types, function types, and type arguments.
|
|
It cannot be used in a type alias body.
|
|
|
|
The `this` type has also been <<this-adoption,adopted in the standard library>>.
|
|
|
|
To read more about the design, see https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0029-self-type.adoc[SPICE-0029].
|
|
|
|
=== Better `new {}` inference
|
|
|
|
The `new {}` expression can now correctly infer its parent in more positions (https://github.com/apple/pkl/pull/1768[#1768], https://github.com/apple/pkl/pull/1824[#1824], https://github.com/apple/pkl/pull/1845[#1845], https://github.com/apple/pkl/pull/1847[#1847], https://github.com/apple/pkl/pull/1857[#1857]).
|
|
|
|
An xref:language-reference:index.adoc#implicitly-typed-new[implicitly typed `new {}` expression] tells Pkl to infer the parent when amending.
|
|
When used inside a property, for example, it amends the class property default.
|
|
|
|
Using `new {}` in the following positions currently throw, and will work in Pkl 0.33:
|
|
|
|
* Method arguments
|
|
* Let bindings
|
|
|
|
[source,pkl]
|
|
----
|
|
class Bird {
|
|
name: String
|
|
}
|
|
|
|
function greet(bird: Bird): String = "Hello, \(bird.name)"
|
|
|
|
greeting1 = greet(new { name = "Pigeon" }) // <1>
|
|
|
|
greeting2 =
|
|
let (bird: Bird = new { name = "Parrot" }) // <2>
|
|
greet(bird)
|
|
----
|
|
<1> The argument is inferred to be a `Bird`.
|
|
<2> The `let` binding is inferred to be a `Bird`.
|
|
|
|
Inference is not available where the parameter type is not known ahead of time.
|
|
Additionally, it cannot be used for constructor methods like `List()`, generic methods like `Pair()`, and `Function.apply()`.
|
|
|
|
It is an error for the parameter type to be `this` or `module`.
|
|
|
|
=== Support for parsing `.netrc` files into HTTP headers
|
|
|
|
Pkl now supports parsing `.netrc` files to configure HTTP Basic authentication headers (https://github.com/apple/pkl/pull/1817[#1817], https://github.com/apple/pkl/pull/1854[#1854]).
|
|
|
|
A new method is introduced called `netRcHeaders()` on class `pkl.EvaluatorSettings#Http`.
|
|
|
|
It can be used to read credentials directly from a local `.netrc` file and mapped to HTTP `Authorization` headers:
|
|
|
|
.~/.config/pkl/settings.pkl
|
|
[source,pkl]
|
|
----
|
|
amends "pkl:settings"
|
|
|
|
http {
|
|
headers = netRcHeaders(read("/Users/johnappleseed/.netrc"))
|
|
}
|
|
----
|
|
|
|
It follows standard `curl` parsing rules, supporting comments, quoted values, and escaped characters.
|
|
|
|
Thank you to https://github.com/ayashjorden[@ayashjorden] for their contributions to this feature!
|
|
|
|
=== CLI Changes
|
|
|
|
==== Package installation to the local cache
|
|
|
|
The `pkl project package` command has gained a new `--install` flag that triggers installation of the built package(s) into the module cache (https://github.com/apple/pkl/pull/1795[#1795]).
|
|
|
|
Local cache installation is useful for local end-to-end testing of dependency trees.
|
|
This functionality is also available via pkl-gradle.
|
|
|
|
|
|
==== Default file locations
|
|
|
|
For new setups, the CLI no longer stores anything under `~/.pkl` (https://github.com/apple/pkl/pull/1809[#1809]).
|
|
|
|
It uses XDG-style locations on Unix and Known Folder locations on Windows:
|
|
|
|
[cols="1,2,2,2",options="header"]
|
|
|===
|
|
| Concern | Unix (Linux/macOS) | Windows | Legacy fallback
|
|
|
|
| Package cache
|
|
| `~/.cache/pkl`
|
|
| `$LOCALAPPDATA/pkl/Cache`
|
|
| none
|
|
|
|
| Settings file
|
|
| `~/.config/pkl/settings.pkl`
|
|
| `$APPDATA/pkl/settings.pkl`
|
|
| `~/.pkl/settings.pkl`
|
|
|
|
| CA certificates
|
|
| `~/.config/pkl/cacerts`
|
|
| `$APPDATA/pkl/cacerts`
|
|
| `~/.pkl/cacerts`
|
|
|
|
| REPL history
|
|
| `~/.local/state/pkl/repl-history`
|
|
| `$LOCALAPPDATA/pkl/repl-history`
|
|
| none
|
|
|===
|
|
|
|
On every OS, these locations can be overridden with XDG-style env vars.
|
|
For example, setting `XDG_CACHE_HOME` will configure the cache directory.
|
|
|
|
Note that the existing `~/.pkl/cache` directory is ignored, so Pkl will download packages to populate its cache if configured to do so.
|
|
|
|
To learn more about this design, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0031-os-base-directories.adoc[SPICE-0031].
|
|
|
|
Thank you to https://github.com/florinungur[@florinungur] for their contributions to this feature!
|
|
|
|
=== Java Library Changes
|
|
|
|
==== `pkl.net#Url` maps to `java.net.URI`
|
|
|
|
The JVM bindings now understand the new `pkl.net#Url` class (https://github.com/apple/pkl/pull/1834[#1834]).
|
|
|
|
The Java and Kotlin code generators generate a `java.net.URI` for a property whose type is pkldoc:Url[pkl:net].
|
|
|
|
Two conversions are added to `org.pkl.config.java.mapper.Conversions`, both part of the preconfigured set:
|
|
|
|
* `pUrlToString` -- gives the same result as `Url.toString()`
|
|
* `pUrlToURI` -- throws `ConversionException` if the URL cannot be represented as a `java.net.URI`
|
|
|
|
=== Standard Library Changes
|
|
|
|
==== `pkl:net`
|
|
|
|
* New module introduced.
|
|
|
|
==== `pkl:syntax`
|
|
|
|
* New module introduced.
|
|
|
|
==== `pkl:base`
|
|
|
|
* New property: pkldoc:String#isValidUrl[]
|
|
* Changed typealias: pkldoc:Uri[] is now `String(isValidUrl)` (<<uri-validates,breaking change>>)
|
|
* [[this-adoption]] Properties refined with `this` type
|
|
** pkldoc:Any.getClass()[] now returns `Class<this>`
|
|
** pkldoc:Any.ifNonNull()[] now accepts an argument of type `(this) \-> Result`
|
|
|
|
==== `pkl:ref`
|
|
|
|
* Renamed class: `Domain` is now `AbstractDomain` (<<reference-changes,breaking change>>)
|
|
* Changed method: `Reference()` now takes type arguments instead of a `Class` parameter (<<reference-changes,breaking change>>)
|
|
* pkldoc:AbstractDomain.renderReference()[pkl:ref] now accepts a `Reference<this, Any>`
|
|
* No longer considered experimental.
|
|
|
|
==== `pkl:protobuf`
|
|
|
|
* Module deprecated for removal in Pkl 0.34 (https://github.com/apple/pkl/pull/1778[#1778]).
|
|
|
|
== Breaking Changes [small]#💔#
|
|
|
|
=== Removal of macOS amd64 (Intel) Binaries
|
|
|
|
Native `pkl` and `pkldoc` binaries for Intel Mac systems are no longer published with Pkl releases (https://github.com/apple/pkl/pull/1769[#1769]).
|
|
|
|
To continue running new Pkl releases on these systems, use an appropriate Java runtime and the `jpkl` and `jpkldoc` Java executables.
|
|
|
|
=== Type check changes for `Class<T>`
|
|
|
|
Currently, type arguments to the `Class` type are erased.
|
|
Any `Class` value would typecheck against `Class<T>` for any value of `T`.
|
|
|
|
In Pkl 0.33, this erasure has been removed.
|
|
A `Class` value typechecked against `Class<T>` must be a subclass of `T` (https://github.com/apple/pkl/pull/1698[#1698]).
|
|
|
|
If `T` does not resolve to a class type (i.e. it is a union type, nullable type, string literal type, parameterized type, or `nothing`), the type check will always fail.
|
|
|
|
=== Standard library properties marked `const`
|
|
|
|
Some properties within the `pkl:math` and `pkl:release` modules have been marked `const` (https://github.com/apple/pkl/pull/1864[#1864]).
|
|
|
|
Currently, module properties in `pkl:math` and `pkl:release` can be overridden by amending the module.
|
|
Doing this makes little sense; these values are constants and overriding them by amending their module would be odd.
|
|
|
|
The following properties are now `const` and cannot be amended:
|
|
|
|
* pkldoc:minInt[pkl:math]
|
|
* pkldoc:maxInt[pkl:math]
|
|
* pkldoc:maxInt8[pkl:math]
|
|
* pkldoc:maxInt16[pkl:math]
|
|
* pkldoc:maxInt32[pkl:math]
|
|
* pkldoc:maxUInt[pkl:math]
|
|
* pkldoc:maxUInt8[pkl:math]
|
|
* pkldoc:maxUInt16[pkl:math]
|
|
* pkldoc:maxUInt32[pkl:math]
|
|
* pkldoc:minFiniteFloat[pkl:math]
|
|
* pkldoc:maxFiniteFloat[pkl:math]
|
|
* pkldoc:minPositiveFloat[pkl:math]
|
|
* pkldoc:e[pkl:math]
|
|
* pkldoc:pi[pkl:math]
|
|
* pkldoc:current[pkl:release]
|
|
|
|
This is a breaking change for code that looks like this:
|
|
[source,pkl]
|
|
----
|
|
bogusMath = (import("pkl:math")) {
|
|
minInt = -1
|
|
}
|
|
----
|
|
|
|
=== Changes to `join` method on `List`, `Set`, and `Listing`
|
|
|
|
The `join` method in `List`, `Set`, and `Listing` will now call the `toString()` method if overridden on an object (https://github.com/apple/pkl/pull/1872[#1872]).
|
|
|
|
This is a breaking change, but is also considered a bugfix.
|
|
|
|
The following snippet will produce different results:
|
|
|
|
[source,pkl]
|
|
----
|
|
class Bird {
|
|
name: String
|
|
|
|
function toString() = "{ My name is \(name) }"
|
|
}
|
|
|
|
hidden birds: Listing<Bird> = new {
|
|
new { name = "Osprey" }
|
|
new { name = "Eagle" }
|
|
}
|
|
|
|
res = birds.join("\n")
|
|
----
|
|
|
|
Currently, Pkl ignores the `toString()` override, and produces:
|
|
|
|
[source,pkl]
|
|
----
|
|
res = """
|
|
new Bird { name = "Osprey" }
|
|
new Bird { name = "Eagle" }
|
|
"""
|
|
----
|
|
|
|
In Pkl 0.33, the overridden `toString()` will be called, and produces:
|
|
|
|
[source,pkl]
|
|
----
|
|
res = """
|
|
{ My name is Osprey }
|
|
{ My name is Eagle }
|
|
"""
|
|
----
|
|
|
|
[[uri-validates]]
|
|
=== `Uri` validates its value
|
|
|
|
The pkldoc:Uri[] typealias in `pkl:base` is now `String(isValidUrl)` instead of a plain `String` (https://github.com/apple/pkl/pull/1834[#1834]).
|
|
|
|
A value typed as `Uri` must be a valid absolute URL according to https://www.rfc-editor.org/rfc/rfc3986[RFC 3986].
|
|
This means that a relative reference, or a URL containing a character that must be percent-encoded, no longer type-checks:
|
|
|
|
[source,pkl]
|
|
----
|
|
good: Uri = "https://example.com/some%20path"
|
|
|
|
bad1: Uri = "./some/path" // throws: not absolute
|
|
bad2: Uri = "https://example.com/some path" // throws: space must be percent-encoded
|
|
----
|
|
|
|
This affects every standard library member typed as `Uri`, among them pkldoc:Resource#uri[], pkldoc:#importGraph()[pkl:analyze], and the URI-valued properties of pkldoc:#[pkl:Project], pkldoc:#[pkl:EvaluatorSettings] and pkldoc:#[pkl:DocPackageInfo].
|
|
|
|
As a consequence, an invalid URI is now reported as a type constraint violation at the point where it is set, rather than as an error raised later by whatever consumes it.
|
|
|
|
[[reference-changes]]
|
|
=== Changes to `Reference` construction
|
|
|
|
As part of the introduction of generic methods, the `Reference()` constructor method in `pkl:ref` takes the domain and referent types as type arguments instead of taking a `Class` parameter (https://github.com/apple/pkl/pull/1849[#1849]).
|
|
This also makes it possible to construct references to non-class types, such as `Listing<String>` or `String | Int`.
|
|
|
|
The `ref.Domain` class has been renamed to `ref.AbstractDomain`.
|
|
|
|
[source,pkl]
|
|
----
|
|
import "pkl:ref"
|
|
|
|
class MyDomain extends ref.AbstractDomain { // <1>
|
|
function renderReference(reference: ref.Reference<MyDomain, Any>): String = "..."
|
|
}
|
|
|
|
// current
|
|
myRef = ref.Reference(new MyDomain {}, MyReferent, myData)
|
|
|
|
// new
|
|
myRef = ref.Reference<MyDomain, MyReferent>(new MyDomain {}, myData) // <2>
|
|
----
|
|
<1> In Pkl 0.32, `extends ref.Domain`.
|
|
<2> Constraints in the referent type of a `Reference` type annotation are no longer an error, they are ignored.
|
|
|
|
[#parser-rule-change-for-comparison]
|
|
=== Parser rule changes for comparison
|
|
|
|
To support <<generic-methods,generic method calls>>, the syntax for Pkl has changed to permit passing type arguments when calling a method.
|
|
|
|
This purposefully introduces an ambiguity to the grammar: the following expression can be parsed as either a generic method call, or as nested comparison expressions:
|
|
|
|
[source,{pkl-expr}]
|
|
----
|
|
foo < Int > (5)
|
|
----
|
|
|
|
To resolve such ambiguities, such code is preferably parsed as a generic method call.
|
|
|
|
This contrived example is nonsensical today, because it is an error to compare a boolean.
|
|
However, there are times when such code might be written in a well-formed way, for example:
|
|
|
|
[source,pkl]
|
|
----
|
|
res = foo(
|
|
bar < baz,
|
|
qux > (corge + 3)
|
|
)
|
|
----
|
|
|
|
In Pkl 0.33, this above snippet will interpret `bar` as a generic method call.
|
|
To restore the old meaning, wrap the left-hand side with parentheses:
|
|
|
|
[source,diff]
|
|
----
|
|
res = foo(
|
|
- bar < baz,
|
|
+ (bar) < baz,
|
|
qux > (corge + 3)
|
|
)
|
|
----
|
|
|
|
=== `test.catch()` and `test.catchOrNull()` force their result
|
|
|
|
The pkldoc:#catch()[pkl:test] and pkldoc:#catchOrNull()[pkl:test] methods now fully evaluate the value returned by the function they are given (https://github.com/apple/pkl/pull/1910[#1910]).
|
|
|
|
Currently, an error nested inside the returned value was not caught.
|
|
It surfaced later, when the value was used.
|
|
In Pkl 0.33, it is caught, and `catch()` returns its message.
|
|
|
|
=== Abstract methods must be implemented in extending non-abstract classes/modules
|
|
|
|
When extending an abstract class or module, it is now an error if any abstract methods are not implemented.
|
|
|
|
In the following snippet, class `Swallow` is invalid because it does not implement `canCarry`:
|
|
|
|
[source,pkl]
|
|
----
|
|
abstract class Bird {
|
|
abstract function canCarry(fruit: Fruit): Boolean
|
|
}
|
|
|
|
class Swallow extends Bird {
|
|
type: "European" | "African"
|
|
}
|
|
----
|
|
|
|
=== Removal of `module` type in const scopes
|
|
|
|
The `module` type should no longer be used inside typealiases, class bodies, annotation bodies, and `const` scopes.
|
|
Such usages will emit a deprecation warning, and will become a full error in Pkl 0.34 (https://github.com/apple/pkl/pull/1708[#1708]).
|
|
|
|
The `module` type is a self-type, which refers to the `this` of the module.
|
|
When a module is extended, the `module` type refers to the extending module.
|
|
On the other hand, the definition of classes and typealiases cannot be changed by an extending module.
|
|
|
|
The following snippet is misleading, because the module property `friend` _is_ a self-type, whereas class property `Feature.animal` is not.
|
|
|
|
.Bird.pkl
|
|
[source,pkl]
|
|
----
|
|
open module Bird
|
|
|
|
friend: module? // <1>
|
|
|
|
class Feature {
|
|
animal: module? // <2>
|
|
}
|
|
----
|
|
<1> Self-type
|
|
<2> Not a self-type
|
|
|
|
To have clearer semantics, the `module` type can no longer be used inside const scopes.
|
|
|
|
In most cases, such code should be replaced with a self-import.
|
|
|
|
.Bird.pkl
|
|
[source,pkl]
|
|
----
|
|
open module Bird
|
|
|
|
import "Bird.pkl" // <1>
|
|
|
|
class Feature {
|
|
animal: Bird // <2>
|
|
}
|
|
----
|
|
<1> Self-import to use `Bird` as a type
|
|
|
|
=== Protobuf module deprecated
|
|
|
|
The `pkl:protobuf` module is deprecated without replacement (https://github.com/apple/pkl/pull/1778[#1778]).
|
|
|
|
The protobuf module renders Pkl data into the "textproto" format.
|
|
However, Pkl is more expressive than protobuf, which means that Pkl's renderer needs to make rendering choices that are bespoke to Pkl's protobuf renderer.
|
|
|
|
For example, there is no native equivalent for Pkl's `null` literal.
|
|
To address this, Pkl's protobuf renderer renders these as a "null" scalar.
|
|
|
|
These rendering choices are somewhat ad-hoc and likely to break from one usage to the next.
|
|
|
|
Users of protobuf are encouraged render Pkl into https://protobuf.dev/programming-guides/json/[ProtoJSON] instead.
|
|
|
|
== Miscellaneous [small]#🐸#
|
|
|
|
* The `abstract` modifier is now a no-op for properties. (https://github.com/apple/pkl/pull/1781[#1781]).
|
|
* Abstract methods in non-abstract classes and modules are now rejected (https://github.com/apple/pkl/pull/1647[#1647], https://github.com/apple/pkl/pull/1780[#1780]).
|
|
* Enforce that non-abstract classes implement all abstract methods from superclasses (https://github.com/apple/pkl/pull/1785[#1785]).
|
|
* Introduce a new internal representation for type metadata (https://github.com/apple/pkl/pull/1838[#1838]).
|
|
* Improve error message when amending a property with no value set (https://github.com/apple/pkl/pull/1867[#1867]).
|
|
* Use `EnumSet` for token categories (https://github.com/apple/pkl/pull/1803[#1803]).
|
|
* pkldoc:String.toInt()[] now supports all hexadecimal, octal, and binary formats (https://github.com/apple/pkl/pull/1808[#1808]).
|
|
* Handle conditional pluralization in error message (https://github.com/apple/pkl/pull/1848[#1848]).
|
|
* Avoid using Java `Object.toString()` to present language-facing string representations (https://github.com/apple/pkl/pull/1850[#1850]).
|
|
* Unify internal construction of objects (https://github.com/apple/pkl/pull/1873[#1873]).
|
|
* Use module cache directory configured via the CLI or Gradle while evaluating `PklProject` and `settings.pkl` files (https://github.com/apple/pkl/pull/1900[#1900]).
|
|
* Typed values are rendered with more helpful type names in error messages and pkldoc:Any.toString()[] (https://github.com/apple/pkl/pull/1412[#1412]).
|
|
* Add support for customizing spring boot `@ConfigurationProperties` in generated Java/Kotlin code (https://github.com/apple/pkl/pull/1897[#1897]).
|
|
* Improve error message when instantiating a class that cannot be instantiated (https://github.com/apple/pkl/pull/1916[#1916]).
|
|
* Improve error messages when a type alias fails to type check (https://github.com/apple/pkl/pull/1914[#1914]).
|
|
* Add descriptions and groups to the tasks created by the pkl-gradle plugin (https://github.com/apple/pkl/pull/190[#190]).
|
|
* Pkldoc no longer truncates the names of modules that do not start with the package's module name prefix (https://github.com/apple/pkl/pull/1909[#1909]).
|
|
* Reject `file:` URIs that include an authority (https://github.com/apple/pkl/pull/629[#629]).
|
|
* Upgrade to GraalVM 25.2.4 (https://github.com/apple/pkl/pull/1804[#1804]).
|
|
* Improve performance of reading `const` members (https://github.com/apple/pkl/pull/1835[#1835]).
|
|
* Improve performance of `Listing` and `Mapping` type casts (https://github.com/apple/pkl/pull/1837[#1837]).
|
|
* Improve performance of lexical frame resolution (https://github.com/apple/pkl/pull/1842[#1842]).
|
|
* Improve performance of amending `null` parents (https://github.com/apple/pkl/pull/1836[#1836]).
|
|
* Improve performance of annotations without object bodies (https://github.com/apple/pkl/pull/1843[#1843]).
|
|
* Improve performance of `for` and `when` generators (https://github.com/apple/pkl/pull/1844[#1844]).
|
|
* Improve performance of parent property and subscript access (https://github.com/apple/pkl/pull/1853[#1853]).
|
|
* Improve performance of typechecking (https://github.com/apple/pkl/pull/1871[#1871]).
|
|
* Improve performance of string literal union types in more cases (https://github.com/apple/pkl/pull/1875[#1875]).
|
|
* Improve performance of iterating object members (https://github.com/apple/pkl/pull/1879[#1879]). Thank you to https://github.com/odenix[@odenix] for their contributions to this feature!
|
|
* Fix some partial evaluation issues in the GraalVM compiler (https://github.com/apple/pkl/pull/1944[#1944]).
|
|
|
|
== Bug Fixes [small]#🐜#
|
|
|
|
* Fix incorrect behavior when objects are partially forced (https://github.com/apple/pkl/pull/1790[#1790]).
|
|
* Fix issues publishing pkl-gradle (https://github.com/apple/pkl/pull/1777[#1777], https://github.com/apple/pkl/pull/1807[#1807]).
|
|
* Fix resolution of the `module` type in typealias bodies (https://github.com/apple/pkl/pull/1796[#1796]).
|
|
* Don't fail when loading known-malformed CA certs (https://github.com/apple/pkl/pull/1806[#1806]).
|
|
* Fix resolution of type names in typealias constraints (https://github.com/apple/pkl/pull/1826[#1826]).
|
|
* Fix parsing of block comments at the end of a file (https://github.com/apple/pkl/pull/1828[#1828]).
|
|
* Sanitize block comment endings in generated Kotlin doc comments (https://github.com/apple/pkl/pull/1830[#1830]).
|
|
* Enforce max collection size when decoding pkl-binary data (https://github.com/apple/pkl/pull/1831[#1831]).
|
|
* Correctly omit glob imports from reflected imports (https://github.com/apple/pkl/pull/1816[#1816]).
|
|
* Escape characters that cannot appear literally in rendered YAML (https://github.com/apple/pkl/pull/1846[#1846]).
|
|
* Fix invalid prefix when generating spring boot config (https://github.com/apple/pkl/pull/1862[#1862]).
|
|
* Fix `pkl run` behaviors where (sub)commands amend `pkl:Command` without extending it (https://github.com/apple/pkl/pull/1882[#1882]).
|
|
* Fix pkldoc:String.endsWith()[] for overlapping regex matches (https://github.com/apple/pkl/pull/1880[#1880], https://github.com/apple/pkl/pull/1884[#1884]).
|
|
* Fix leak of external reader processes in the language binding server (https://github.com/apple/pkl/pull/1885[#1885]).
|
|
* Fix decoding of `Regex` values from pkl-binary data (https://github.com/apple/pkl/pull/1895[#1895]).
|
|
* Fix `pkl eval` of dependency notation source modules when using multiple file output (https://github.com/apple/pkl/pull/1942[#1942]).
|
|
* Report an error, instead of overflowing the stack, when parsing or formatting code that is nested too deeply (https://github.com/apple/pkl/pull/1918[#1918], https://github.com/apple/pkl/pull/1953[#1953]).
|
|
* Fix type check of the `module` type when it is defined in a parent member body (https://github.com/apple/pkl/pull/1936[#1936]).
|
|
* Fix type check of subscript key types for `Map` and `Mapping` references (https://github.com/apple/pkl/pull/1933[#1933]).
|
|
* Fix `hashCode()` and `==` inconsistency for negative zero in `Duration` and `DataSize` (https://github.com/apple/pkl/pull/1932[#1932]).
|
|
* Fix `hashCode()` inconsistency with `==` for `Listing`, `Duration`, and `DataSize` (https://github.com/apple/pkl/pull/1922[#1922]).
|
|
* Fix `toString()` and `value` of `Duration` and `DataSize` values that are too large to fit in a `Long` (https://github.com/apple/pkl/pull/1935[#1935]).
|
|
* Fix iteration over `Dynamic` objects that have a negative key, such as `new Dynamic { [-1] = 2 }` (https://github.com/apple/pkl/pull/1948[#1948]).
|
|
* Fix enforcement of `const` member access inside methods (https://github.com/apple/pkl/pull/1945[#1945]).
|
|
* Fix parameterized type checks in type alias constraints (https://github.com/apple/pkl/pull/1906[#1906]).
|
|
* Fix resolution of qualified type names (https://github.com/apple/pkl/pull/1915[#1915]).
|
|
* Fix lookaround regexes in pkldoc:String.lastIndexOf()[] and pkldoc:String.replaceLast()[] (https://github.com/apple/pkl/pull/1908[#1908]).
|
|
* Fix formatter instability (https://github.com/apple/pkl/pull/1911[#1911]).
|
|
* Improve normalization of URIs (https://github.com/apple/pkl/pull/1937[#1937], https://github.com/apple/pkl/pull/1954[#1954]).
|
|
* Missing const checks which allow accessing non-const members (https://github.com/apple/pkl/issues/1963[#1963]).
|
|
|
|
== Contributors [small]#🙏#
|
|
|
|
We would like to thank the contributors to this release (in alphabetical order):
|
|
|
|
* https://github.com/AAGAM17[@AAGAM17]
|
|
* https://github.com/aashish254[@aashish254]
|
|
* https://github.com/ayashjorden[@ayashjorden]
|
|
* https://github.com/bioball[@bioball]
|
|
* https://github.com/Carpe-Wang[@Carpe-Wang]
|
|
* https://github.com/dylanpulver[@dylanpulver]
|
|
* https://github.com/florinungur[@florinungur]
|
|
* https://github.com/goutamadwant[@goutamadwant]
|
|
* https://github.com/henriquejsza[@henriquejsza]
|
|
* https://github.com/HT154[@HT154]
|
|
* https://github.com/KushalP[@KushalP]
|
|
* https://github.com/kwy404[@kwy404]
|
|
* https://github.com/mayc7n[@mayc7n]
|
|
* https://github.com/netvl[@netvl]
|
|
* https://github.com/odenix[@odenix]
|
|
* https://github.com/protobufel2[@protobufel2]
|
|
* https://github.com/RushikeshGandhmal[@RushikeshGandhmal]
|
|
* https://github.com/sergiosalvi[@sergiosalvi]
|
|
* https://github.com/sgammon[@sgammon]
|
|
* https://github.com/stackoverflow[@stackoverflow]
|
|
* https://github.com/vinayakj592[@vinayakj592]
|