This is a good first step in the direction of general compile-time evaluation. It is also a necessary step to ensure the safety of the new SwiftPM DSL. I think we may be able to borrow the syntax from the more general case, without designing it.
The use of #
prefix is a well established precedent in Swift to indicate things that are determined at compile time. I think instead of a normal keyword, we should use a #
-prefixed keyword.
The way I see it, we need two:
Parameter:
func foo(input: #evaluated Int) {...}
Static constant:
struct Bar {
static let title = #evaluate( "Bar" )
// OR
static let title: #evaluated String = "Bar"
// OR (most verbose, the actual full syntax)
static let title: #evaluated String = #evaluate( "Bar" )
// For now, #evaluate() only accepts literals )
}
Constant property:
struct Baz {
let title: #evaluated String
init(title: #evaluated String) {
self.title = title
}
}
let b1 = Baz(title: "One")
// Also valid:
let b2 = Baz(title: #evaluate("Two") )
//Also valid:
let t = #evaluate("Three")
let b2 = Baz(title: t)
Constant static or property protocol requirement:
protocol NeedsConstGreeting {
static let greeting: #evaluated String
let instanceGreeting: #evaluated String
}
Using var for #evaluated types is prohibited:
var x1: #evaluated String // Error: a pre-evaluated String can't be modified. Use `let` instead.
But initializing a var with a compile-time constant is fine:
var x2: String = #evaluate("Hello")
We can interpret the above as a subtype relationship between Type
and #evaluated Type
I believe the above design is general enough to cover the cases mentioned in the Future Directions section and constant expressions thread.
EDIT: Removed duplicated text. Somehow I managed to paste the text from my editor twice.