mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SE-0492: Add support for closures (with no captures) into @section expressions
This commit is contained in:
@@ -832,6 +832,8 @@ ERROR(const_unsupported_type_expr,none,
|
||||
"type expressions not supported in a constant expression", ())
|
||||
ERROR(const_unsupported_closure,none,
|
||||
"closures not supported in a constant expression", ())
|
||||
ERROR(const_unsupported_closure_with_captures,none,
|
||||
"closures with captures not supported in a constant expression", ())
|
||||
ERROR(const_unsupported_keypath,none,
|
||||
"keypaths not supported in a constant expression", ())
|
||||
ERROR(const_opaque_decl_ref,none,
|
||||
|
||||
@@ -46,6 +46,7 @@ enum IllegalConstErrorDiagnosis {
|
||||
TypeExpression,
|
||||
KeyPath,
|
||||
Closure,
|
||||
ClosureWithCaptures,
|
||||
OpaqueDeclRef,
|
||||
OpaqueFuncDeclRef,
|
||||
NonConventionCFunc,
|
||||
@@ -82,6 +83,9 @@ static void diagnoseError(const Expr *errorExpr,
|
||||
case Closure:
|
||||
diags.diagnose(errorLoc, diag::const_unsupported_closure);
|
||||
break;
|
||||
case ClosureWithCaptures:
|
||||
diags.diagnose(errorLoc, diag::const_unsupported_closure_with_captures);
|
||||
break;
|
||||
case OpaqueDeclRef:
|
||||
diags.diagnose(errorLoc, diag::const_opaque_decl_ref);
|
||||
break;
|
||||
@@ -222,9 +226,19 @@ checkSupportedWithSectionAttribute(const Expr *expr,
|
||||
if (isa<KeyPathExpr>(expr))
|
||||
return std::make_pair(expr, KeyPath);
|
||||
|
||||
// Closure expressions are not supported in constant expressions
|
||||
if (isa<AbstractClosureExpr>(expr))
|
||||
return std::make_pair(expr, Closure);
|
||||
// Closures are allowed if they have no captures
|
||||
if (auto closureExpr = dyn_cast<ClosureExpr>(expr)) {
|
||||
TypeChecker::computeCaptures(const_cast<ClosureExpr *>(closureExpr));
|
||||
if (!closureExpr->getCaptureInfo().isTrivial()) {
|
||||
return std::make_pair(expr, ClosureWithCaptures);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// No auto-closures
|
||||
if (isa<AbstractClosureExpr>(expr)) {
|
||||
return std::make_pair(expr, Default);
|
||||
}
|
||||
|
||||
// Function conversions are allowed if the conversion is to '@convention(c)'
|
||||
if (auto functionConvExpr = dyn_cast<FunctionConversionExpr>(expr)) {
|
||||
|
||||
@@ -28,6 +28,17 @@ func bar(x: Int) -> String { return "test" }
|
||||
@section("mysection") let funcRef1 = foo // ok
|
||||
@section("mysection") let funcRef2 = bar // ok
|
||||
|
||||
// closures
|
||||
@section("mysection") let closure1 = { }
|
||||
@section("mysection") let closure2 = { return 42 }
|
||||
@section("mysection") let closure3 = { (x: Int) in return x + 1 }
|
||||
@section("mysection") let closure4: () -> Void = { }
|
||||
@section("mysection") let closure5: (Int) -> Int = { x in x * 2 }
|
||||
@section("mysection") let closure6: @convention(c) (Int) -> Int = { x in x * 2 }
|
||||
struct W {
|
||||
@section("mysection") static let closure7: @convention(c) (Int) -> Int = { x in x * 2 }
|
||||
}
|
||||
|
||||
// metatypes - TODO
|
||||
//@section("mysection") let metatype1 = Int.self
|
||||
|
||||
@@ -56,6 +67,15 @@ func bar(x: Int) -> String { return "test" }
|
||||
// CHECK: @"$s9SectionIR12boolLiteral2Sbvp" = {{.*}}constant %TSb zeroinitializer, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8funcRef1Siycvp" = {{.*}}constant %swift.function { ptr @"$s9SectionIR3fooSiyF{{.*}}", ptr null }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8funcRef2ySSSicvp" = {{.*}}constant %swift.function { ptr @"$s9SectionIR3bar1xSSSi_tF{{.*}}", ptr null }, section "mysection"
|
||||
|
||||
// CHECK: @"$s9SectionIR8closure1yycvp" = {{.*}}constant %swift.function { {{.*}} }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8closure2Siycvp" = {{.*}}constant %swift.function { {{.*}} }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8closure3yS2icvp" = {{.*}}constant %swift.function { {{.*}} }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8closure4yycvp" = {{.*}}constant %swift.function { {{.*}} }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8closure5yS2icvp" = {{.*}}constant %swift.function { {{.*}} }, section "mysection"
|
||||
// CHECK: @"$s9SectionIR8closure6yS2iXCvp" = {{.*}}constant ptr @"$s9SectionIR8closure6yS2iXCvpfiS2icfU_To", section "mysection"
|
||||
// CHECK: @"$s9SectionIR1WV8closure7yS2iXCvpZ" = {{.*}}constant ptr @"$s9SectionIR1WV8closure7yS2iXCvpZfiS2icfU_To", section "mysection"
|
||||
|
||||
// CHECK: @"$s9SectionIR6tuple1Si_S2iSdSbtvp" = {{.*}}constant <{ %TSi, %TSi, %TSi, {{.*}} }> <{ %TSi <{ {{i64|i32}} 1 }>, %TSi <{ {{i64|i32}} 2 }>, %TSi <{ {{i64|i32}} 3 }>, {{.*}} }>, section "mysection"
|
||||
// CHECK: @"$s9SectionIR6tuple2Si_SfSbtvp" = {{.*}}constant <{ %TSi, %TSf, %TSb }> <{ %TSi <{ {{i64|i32}} 42 }>, %TSf <{ float 0x40091EB860000000 }>, %TSb zeroinitializer }>, section "mysection"
|
||||
// CHECK: @"$s9SectionIR6tuple3Siyc_SSSictvp" = {{.*}}constant <{ %swift.function, %swift.function }> <{ %swift.function { ptr @"$s9SectionIR3fooSiyF{{.*}}", ptr null }, %swift.function { ptr @"$s9SectionIR3bar1xSSSi_tF{{.*}}", ptr null } }>, section "mysection"
|
||||
|
||||
@@ -53,7 +53,7 @@ func bar(x: Int) -> String { return "test" }
|
||||
@section("mysection") let invalidFuncRef1 = foo()
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidFuncRef2 = Bool.self.random
|
||||
// expected-error@-1{{closures not supported in a constant expression}}
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidFuncRef3 = (Bool.self as Bool.Type).random
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
|
||||
@@ -61,11 +61,38 @@ func bar(x: Int) -> String { return "test" }
|
||||
@section("mysection") let invalidGenericFunc = [Int].randomElement
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
|
||||
// closures (should be rejected)
|
||||
@section("mysection") let invalidClosure1 = { }
|
||||
// expected-error@-1{{closures not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure2 = { return 42 }
|
||||
// expected-error@-1{{closures not supported in a constant expression}}
|
||||
// closures
|
||||
@section("mysection") let closure1 = { } // ok
|
||||
@section("mysection") let closure2 = { return 42 } // ok
|
||||
@section("mysection") let closure3 = { (x: Int) in return x + 1 } // ok
|
||||
@section("mysection") let closure4: () -> Void = { } // ok
|
||||
@section("mysection") let closure5: (Int) -> Int = { x in x * 2 } // ok
|
||||
@section("mysection") let closure6: @convention(c) (Int) -> Int = { x in x * 2 } // ok
|
||||
struct W {
|
||||
@section("mysection") static let closure7: @convention(c) (Int) -> Int = { x in x * 2 } // ok
|
||||
}
|
||||
|
||||
let capturedVar = 10
|
||||
class TestClass {}
|
||||
var capturedMutableVar = TestClass()
|
||||
|
||||
// closures with captures (should be rejected)
|
||||
@section("mysection") let invalidClosure1 = { capturedVar }
|
||||
// expected-error@-1{{closures with captures not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure2 = { return capturedVar + 1 }
|
||||
// expected-error@-1{{closures with captures not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure3 = { [capturedVar] in return capturedVar }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure4 = { [weak capturedMutableVar] in return capturedMutableVar }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure5 = { [unowned capturedMutableVar] in return capturedMutableVar }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure6 = { [capturedVar, capturedMutableVar] in return 42 }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure7 = { [renamed = capturedVar] in return renamed * 2 }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
@section("mysection") let invalidClosure8 = { [computed = capturedVar + 5] in return computed }
|
||||
// expected-error@-1{{not supported in a constant expression}}
|
||||
|
||||
struct S { }
|
||||
enum E { case a }
|
||||
|
||||
Reference in New Issue
Block a user