Files
pkl/docs/modules/release-notes/pages/0.33.adoc
T
c39b1e7a59 Add release notes for 0.33 (#1939)
Co-authored-by: Jen Basch <jbasch@apple.com>
Co-authored-by: Dan Chao <dan.chao@apple.com>
2026-11-05 12:20:48 -08:00

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]