mirror of
https://github.com/apple/pkl.git
synced 2026-05-28 01:29:15 +02:00
Execute typechecks eagerly when within a constraint (#964)
This changes the language to check all types eagerly when within a type constraint. This addresses two regressions in the language: 1. Type constraints are too relaxed (listing/mapping parameters may not be checked) 2. Failing type constraints hide members that were forced during execution of the constraint
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
typealias EmailAddress = String(matches(Regex(#".+@\S+|.+<\S+@\S+>"#)))
|
||||
|
||||
class MyClass {
|
||||
emails: Listing<EmailAddress>
|
||||
}
|
||||
|
||||
myClass: MyClass
|
||||
|
||||
others: Listing<module(this != module)>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
amends ".../input-helper/classes/MyClass.pkl"
|
||||
|
||||
myClass {
|
||||
emails {
|
||||
"baz@bar.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import "pkl:test"
|
||||
|
||||
const local isOddLengthOfBirds = (it: Listing<Bird>) -> it.length.isOdd
|
||||
|
||||
class Bird
|
||||
|
||||
class MyTest {
|
||||
// function parameter type should be checked eagerly
|
||||
birds: Listing(isOddLengthOfBirds) = new {
|
||||
1
|
||||
2
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
res = test.catch(() -> new MyTest {}.birds)
|
||||
@@ -0,0 +1,14 @@
|
||||
// This test executes constraint `EmailAddress` within `MyClass` from two different root nodes:
|
||||
// - ListingOrMappingTypeCastNode
|
||||
// - PropertyTypeNode
|
||||
amends ".../input-helper/classes/MyClass.pkl"
|
||||
|
||||
myClass {
|
||||
emails {
|
||||
"foo@bar.com"
|
||||
}
|
||||
}
|
||||
|
||||
others {
|
||||
import(".../input-helper/classes/myClass1.pkl")
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// Error message should include `new Bird { name = "Bob" }`
|
||||
birds: Listing(firstOneIsSandy) = new {
|
||||
new Bird { name = "Bob" }
|
||||
new Bird { name = "Bob" }
|
||||
}
|
||||
|
||||
hidden firstOneIsSandy = (it: Listing<Bird>) -> it[0].name == "Sandy"
|
||||
|
||||
class Bird { name: String }
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// Error message should include `new Bird { name = "Bob" }`
|
||||
birds: Listing(
|
||||
let (myself: Listing<Bird> = this)
|
||||
myself[0].name == "Sandy"
|
||||
) =
|
||||
new {
|
||||
new Bird { name = "Bob" }
|
||||
new Bird { name = "Bob" }
|
||||
}
|
||||
|
||||
class Bird { name: String }
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// typechecks within child frames should also be eagerly checked
|
||||
foo: Listing(toList().every((it: Listing<Bird>) -> it[0].name == "Bob")) = new {
|
||||
new Listing {
|
||||
new Bird { name = "Eagle" }
|
||||
new Bird { name = "Quail" }
|
||||
}
|
||||
}
|
||||
|
||||
class Bird { name: String }
|
||||
@@ -0,0 +1 @@
|
||||
res = "Expected value of type `constraints13#Bird`, but got type `Int`. Value: 1"
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
myClass {
|
||||
emails {
|
||||
"foo@bar.com"
|
||||
}
|
||||
}
|
||||
others {
|
||||
new {
|
||||
myClass {
|
||||
emails {
|
||||
"baz@bar.com"
|
||||
}
|
||||
}
|
||||
others {}
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Type constraint `firstOneIsSandy` violated.
|
||||
Value: new Listing { new Bird { name = "Bob" }; new Bird { name = ? } }
|
||||
|
||||
x | birds: Listing(firstOneIsSandy) = new {
|
||||
^^^^^^^^^^^^^^^
|
||||
at constraintDetails1#birds (file:///$snippetsDir/input/errors/constraintDetails1.pkl)
|
||||
|
||||
x | birds: Listing(firstOneIsSandy) = new {
|
||||
^^^^^
|
||||
at constraintDetails1#birds (file:///$snippetsDir/input/errors/constraintDetails1.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
–– Pkl Error ––
|
||||
Type constraint `let (myself: Listing<Bird> = this)
|
||||
myself[0].name == "Sandy"` violated.
|
||||
Value: new Listing { new Bird { name = "Bob" }; new Bird { name = ? } }
|
||||
|
||||
x | let (myself: Listing<Bird> = this)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at constraintDetails2#birds (file:///$snippetsDir/input/errors/constraintDetails2.pkl)
|
||||
|
||||
x | new {
|
||||
^^^^^
|
||||
at constraintDetails2#birds (file:///$snippetsDir/input/errors/constraintDetails2.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Type constraint `toList().every((it: Listing<Bird>) -> it[0].name == "Bob")` violated.
|
||||
Value: new Listing { new Listing { new Bird { name = "Eagle" }; new Bird { name = ? ...
|
||||
|
||||
x | foo: Listing(toList().every((it: Listing<Bird>) -> it[0].name == "Bob")) = new {
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at constraintDetails3#foo (file:///$snippetsDir/input/errors/constraintDetails3.pkl)
|
||||
|
||||
x | foo: Listing(toList().every((it: Listing<Bird>) -> it[0].name == "Bob")) = new {
|
||||
^^^^^
|
||||
at constraintDetails3#foo (file:///$snippetsDir/input/errors/constraintDetails3.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
Reference in New Issue
Block a user