diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 90da1f1be299b..c4b5702c657a2 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -302,10 +302,8 @@ extractCompileTimeValue(Expr *expr, const DeclContext *declContext) { case ExprKind::Call: { auto callExpr = cast(expr); - auto functionKind = callExpr->getFn()->getKind(); - if (functionKind == ExprKind::DeclRef) { - auto declRefExpr = cast(callExpr->getFn()); + if (auto declRefExpr = dyn_cast(callExpr->getFn())) { auto identifier = declRefExpr->getDecl()->getName().getBaseIdentifier().str().str(); @@ -314,17 +312,15 @@ extractCompileTimeValue(Expr *expr, const DeclContext *declContext) { return std::make_shared(identifier, parameters); } - if (functionKind == ExprKind::ConstructorRefCall) { + if (auto constructorRefCall = dyn_cast(callExpr->getFn())) { std::vector parameters = extractFunctionArguments(callExpr->getArgs(), declContext); return std::make_shared(callExpr->getType(), parameters); } - if (functionKind == ExprKind::DotSyntaxCall) { - auto dotSyntaxCallExpr = cast(callExpr->getFn()); + if (auto dotSyntaxCallExpr = dyn_cast(callExpr->getFn())) { auto fn = dotSyntaxCallExpr->getFn(); - if (fn->getKind() == ExprKind::DeclRef) { - auto declRefExpr = cast(fn); + if (auto declRefExpr = dyn_cast(fn)) { auto baseIdentifierName = declRefExpr->getDecl()->getName().getBaseIdentifier().str().str(); @@ -355,14 +351,24 @@ extractCompileTimeValue(Expr *expr, const DeclContext *declContext) { } } + if (auto functionConversionExpr = dyn_cast(callExpr->getFn())) { + if (auto declRefExpr = dyn_cast(functionConversionExpr->getSubExpr())) { + auto identifier = + declRefExpr->getDecl()->getName().getBaseIdentifier().str().str(); + + std::vector parameters = + extractFunctionArguments(callExpr->getArgs(), declContext); + return std::make_shared(identifier, parameters); + } + } + break; } case ExprKind::DotSyntaxCall: { auto dotSyntaxCallExpr = cast(expr); auto fn = dotSyntaxCallExpr->getFn(); - if (fn->getKind() == ExprKind::DeclRef) { - auto declRefExpr = cast(fn); + if (auto declRefExpr = dyn_cast(fn)) { auto caseName = declRefExpr->getDecl()->getName().getBaseIdentifier().str().str(); return std::make_shared(caseName, std::nullopt); @@ -507,6 +513,12 @@ extractCompileTimeValue(Expr *expr, const DeclContext *declContext) { auto derivedExpr = cast(expr); return extractCompileTimeValue(derivedExpr->getSubExpr(), declContext); } + + case ExprKind::OpenExistential: { + auto openExistentialExpr = cast(expr); + return extractCompileTimeValue(openExistentialExpr->getExistentialValue(), declContext); + } + default: { break; } diff --git a/test/ConstExtraction/ExtractOpenExistential.swift b/test/ConstExtraction/ExtractOpenExistential.swift new file mode 100644 index 0000000000000..1c2f784492c82 --- /dev/null +++ b/test/ConstExtraction/ExtractOpenExistential.swift @@ -0,0 +1,70 @@ +// RUN: %empty-directory(%t) +// RUN: echo "[MyProto]" > %t/protocols.json + +// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractOpenExistential.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s +// RUN: cat %t/ExtractOpenExistential.swiftconstvalues 2>&1 | %FileCheck %s + +protocol MyProto {} + +protocol ExampleProtocol { + var protocolProperty: String { get } +} + +struct ConcreteType: ExampleProtocol { + let protocolProperty: String = "Concrete implementation" +} + +func useExistential(_ example: any ExampleProtocol) -> String { + return example.protocolProperty +} + +public struct External: MyProto { + static let existentialValue = useExistential(ConcreteType()) +} + + +// CHECK: [ +// CHECK-NEXT: { +// CHECK-NEXT: "typeName": "ExtractOpenExistential.External", +// CHECK-NEXT: "mangledTypeName": "22ExtractOpenExistential8ExternalV", +// CHECK-NEXT: "kind": "struct", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractOpenExistential.swift", +// CHECK-NEXT: "line": 21, +// CHECK-NEXT: "conformances": [ +// CHECK-NEXT: "ExtractOpenExistential.MyProto" +// CHECK-NEXT: ], +// CHECK-NEXT: "allConformances": [ +// CHECK-NEXT: { +// CHECK-NEXT: "protocolName": "ExtractOpenExistential.MyProto" +// CHECK-NEXT: "conformanceDefiningModule": "ExtractOpenExistential" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "associatedTypeAliases": [], +// CHECK-NEXT: "properties": [ +// CHECK-NEXT: { +// CHECK-NEXT: "label": "existentialValue", +// CHECK-NEXT: "type": "Swift.String", +// CHECK-NEXT: "mangledTypeName": "n/a - deprecated", +// CHECK-NEXT: "isStatic": "true", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractOpenExistential.swift", +// CHECK-NEXT: "line": 22, +// CHECK-NEXT: "valueKind": "FunctionCall", +// CHECK-NEXT: "value": { +// CHECK-NEXT: "name": "useExistential", +// CHECK-NEXT: "arguments": [ +// CHECK-NEXT: { +// CHECK-NEXT: "label": "", +// CHECK-NEXT: "type": "any ExtractOpenExistential.ExampleProtocol", +// CHECK-NEXT: "valueKind": "InitCall", +// CHECK-NEXT: "value": { +// CHECK-NEXT: "type": "ExtractOpenExistential.ConcreteType", +// CHECK-NEXT: "arguments": [] +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ]