Looking at your project, those don't appear to be bugs in the specification or implementation of SE-0422, just general constraints on type-checking.
Given that your #identity macros expand to { value }() (where value is an identifier but is not defined by the macro itself), and given the implementation of printNumeric() as:
func printNumeric(_ value: some Numeric = #identity1) {
print("The numeric value is", value)
}
In the first example:
// ❌ Compilation error: "Generic parameter 'some Numeric' could not be inferred"
printNumeric()
There is no type information the compiler can use to infer the type of value, and thus the program is ill-formed.
In the second example:
// ❌ Compilation error: "Cannot find 'value' in scope" (because it extends in-place)
func printNumeric(_ value: some Numeric = #identity2) {
print("The numeric value is", value)
}
If you replace #identity2 with its expansion ({ value }()), the compiler emits the same error. This error is expected because default arguments cannot be self-referential. The compiler would also emit this error for your first example if it could get past the "could not be inferred" issue. For example:
func printNumeric<T: Numeric>(_ type: T.Type, _ value: T = #identity1) {
print("The numeric value is", value)
}
printNumeric(Int.self) // ❌ Compilation error: "Cannot find 'value' in scope"
If we expand the macros to 1 / 0 instead of { value }(), we can see that the expression is not callee-evaluated because the compiler does not emit a division-by-zero error until/unless the function is called.
Another really unfortunate bug with SE-0422: expression macros are invoked with an empty lexicalContext when expanded as a default argument (GH issue):
func test(_ loc: SourceLocation = #here) {
print(loc)
}
#Playground {
test() // lexicalContext is empty
test(#here) // lexicalContext works as expected
}
I think you missed one crucial thing: according to SE-0422 the macro will not be expended “in-place“. It will be expended at a call-side. That’s the whole point.
So the code in your very last snippet will do compile and work! You can just try to run it by yourself
func printNumeric<T: Numeric>(_ type: T.Type, _ value: T = #identity1) {
print("The numeric value is", value)
}
func start(with value: Int) {
printNumeric(Int.self) // ✅ Compiles & Works
}
// Or in a more general form
func start(with value: some Numeric) {
printNumeric(type(of: value)) // ✅ Compiles & Works
}
At the same time this example of yours really helps to understand that the “issue1“ is indeed not a bug. It illustrates very clearly that the type information is indeed not being passed in this scenario.
But as for “issue2“ it still looks like a potential bug for me. Namely: the macro expends “in-place“, while it should expends at the call-side, according to SE-0422.
The expansion still ultimately happens at the call site, however the compiler first type-checks default argument expressions (which as I noted it does for non-macro-based values too.) I'll let the code owners confirm this is by design, but the behaviour is observably correct in other macros like #file or Swift Testing's #_sourceLocation.