diff --git a/include/swift/AST/ConstTypeInfo.h b/include/swift/AST/ConstTypeInfo.h index e7c0de82ce2a7..6b908fadafb0b 100644 --- a/include/swift/AST/ConstTypeInfo.h +++ b/include/swift/AST/ConstTypeInfo.h @@ -43,6 +43,7 @@ class CompileTimeValue { StaticFunctionCall, MemberReference, InterpolatedString, + NilLiteral, Runtime }; @@ -72,6 +73,22 @@ class RawLiteralValue : public CompileTimeValue { std::string Value; }; +/// A representation of an Optional value declared as nil +/// or left undeclared. +/// +/// Nil values were previously represented as RawLiteralValue with +/// value "nil". This caused ambiguous values when extracting values, +/// such as an Optional of value "nil". + +class NilLiteralValue : public CompileTimeValue { +public: + NilLiteralValue() : CompileTimeValue(ValueKind::NilLiteral) {} + + static bool classof(const CompileTimeValue *T) { + return T->getKind() == ValueKind::NilLiteral; + } +}; + struct FunctionParameter { std::string Label; swift::Type Type; diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 0818a94d86d22..e3618ee8980b5 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -198,8 +198,7 @@ static std::optional extractRawLiteral(Expr *expr) { switch (expr->getKind()) { case ExprKind::BooleanLiteral: case ExprKind::FloatLiteral: - case ExprKind::IntegerLiteral: - case ExprKind::NilLiteral: { + case ExprKind::IntegerLiteral: { std::string literalOutput; llvm::raw_string_ostream OutputStream(literalOutput); expr->printConstExprValue(&OutputStream, nullptr); @@ -230,7 +229,6 @@ static std::shared_ptr extractCompileTimeValue(Expr *expr) { case ExprKind::BooleanLiteral: case ExprKind::FloatLiteral: case ExprKind::IntegerLiteral: - case ExprKind::NilLiteral: case ExprKind::StringLiteral: { auto rawLiteral = extractRawLiteral(expr); if (rawLiteral.has_value()) { @@ -240,6 +238,10 @@ static std::shared_ptr extractCompileTimeValue(Expr *expr) { break; } + case ExprKind::NilLiteral: { + return std::make_shared(); + } + case ExprKind::Array: { auto arrayExpr = cast(expr); std::vector> elementValues; @@ -710,6 +712,11 @@ void writeValue(llvm::json::OStream &JSON, break; } + case CompileTimeValue::ValueKind::NilLiteral: { + JSON.attribute("valueKind", "NilLiteral"); + break; + } + case CompileTimeValue::ValueKind::InitCall: { auto initCallValue = cast(value); diff --git a/test/ConstExtraction/ExtractFromObjcImplementationExtension.swift b/test/ConstExtraction/ExtractFromObjcImplementationExtension.swift index 502bf64790a72..3a541db2e1457 100644 --- a/test/ConstExtraction/ExtractFromObjcImplementationExtension.swift +++ b/test/ConstExtraction/ExtractFromObjcImplementationExtension.swift @@ -24,7 +24,7 @@ extension ImplClass: MyProto { // CHECK: "label": "defaultNilProperty", // CHECK: "type": "Swift.Optional", -// CHECK: "value": "nil" +// CHECK: "valueKind": "NilLiteral" // CHECK: "label": "notStoredProperty", // CHECK: "type": "Swift.Bool", diff --git a/test/ConstExtraction/ExtractLiterals.swift b/test/ConstExtraction/ExtractLiterals.swift index ed2081763fca6..fd14991d970b6 100644 --- a/test/ConstExtraction/ExtractLiterals.swift +++ b/test/ConstExtraction/ExtractLiterals.swift @@ -94,6 +94,12 @@ public struct PropertyWrappers : MyProto { var projectedValue: (V, V?) { (self.value, self.lastValue) } } +public struct Optionals: MyProto { + let int1: Bool? = nil + let string1: String? + static var float1: Float? +} + // CHECK: [ // CHECK-NEXT: { // CHECK-NEXT: "typeName": "ExtractLiterals.Bools", @@ -131,8 +137,7 @@ public struct PropertyWrappers : MyProto { // CHECK-NEXT: "isComputed": "false", // CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractLiterals.swift", // CHECK-NEXT: "line": 11, -// CHECK-NEXT: "valueKind": "RawLiteral", -// CHECK-NEXT: "value": "nil" +// CHECK-NEXT: "valueKind": "NilLiteral" // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, @@ -617,5 +622,54 @@ public struct PropertyWrappers : MyProto { // CHECK-NEXT: "valueKind": "Runtime" // CHECK-NEXT: } // CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "typeName": "ExtractLiterals.Optionals", +// CHECK-NEXT: "mangledTypeName": "15ExtractLiterals9OptionalsV", +// CHECK-NEXT: "kind": "struct", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractLiterals.swift", +// CHECK-NEXT: "line": 97, +// CHECK-NEXT: "conformances": [ +// CHECK-NEXT: "ExtractLiterals.MyProto" +// CHECK-NEXT: ], +// CHECK-NEXT: "allConformances": [ +// CHECK-NEXT: { +// CHECK-NEXT: "protocolName": "ExtractLiterals.MyProto", +// CHECK-NEXT: "conformanceDefiningModule": "ExtractLiterals" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "associatedTypeAliases": [], +// CHECK-NEXT: "properties": [ +// CHECK-NEXT: { +// CHECK-NEXT: "label": "int1", +// CHECK-NEXT: "type": "Swift.Optional", +// CHECK-NEXT: "mangledTypeName": "n/a - deprecated", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractLiterals.swift", +// CHECK-NEXT: "line": 98, +// CHECK-NEXT: "valueKind": "NilLiteral" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "string1", +// CHECK-NEXT: "type": "Swift.Optional", +// CHECK-NEXT: "mangledTypeName": "n/a - deprecated", +// CHECK-NEXT: "isStatic": "false", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractLiterals.swift", +// CHECK-NEXT: "line": 99, +// CHECK-NEXT: "valueKind": "Runtime" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "label": "float1", +// CHECK-NEXT: "type": "Swift.Optional", +// CHECK-NEXT: "mangledTypeName": "n/a - deprecated", +// CHECK-NEXT: "isStatic": "true", +// CHECK-NEXT: "isComputed": "false", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractLiterals.swift", +// CHECK-NEXT: "line": 100, +// CHECK-NEXT: "valueKind": "NilLiteral" +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT:]