diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def
index 9f1d211f3f3..a3aefc67b54 100644
--- a/include/swift/AST/KnownIdentifiers.def
+++ b/include/swift/AST/KnownIdentifiers.def
@@ -62,7 +62,7 @@ IDENTIFIER_WITH_NAME(MaxBuiltinIntegerType, "_MaxBuiltinIntegerType")
IDENTIFIER(IntegerLiteralType)
IDENTIFIER_WITH_NAME(AllZeros, "allZeros")
IDENTIFIER_WITH_NAME(BoolValue, "boolValue")
-IDENTIFIER_WITH_NAME(ConvertFromNilLiteral, "convertFromNilLiteral")
+IDENTIFIER_WITH_NAME(NilLiteral, "nilLiteral")
IDENTIFIER_WITH_NAME(ConvertFromIntegerLiteral, "convertFromIntegerLiteral")
IDENTIFIER_WITH_NAME(ConvertFromBuiltinIntegerLiteral,
"_convertFromBuiltinIntegerLiteral")
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index a1c5dbcdb13..f5f1bf32cde 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -564,58 +564,71 @@ static void makeOptionSetAllZerosProperty(StructDecl *optionSetDecl,
// Build the NilLiteralConvertible conformance:
//
// extension NSSomeOptionSet : NilLiteralConvertible {
-// static func convertFromNilLiteral() -> S {
-// return S()
+// init(nilLiteral: ())
+// self = S()
// }
// }
-static FuncDecl *makeNilLiteralConformance(StructDecl *optionSetDecl,
- ValueDecl *valueDecl) {
+static ConstructorDecl *makeNilLiteralConformance(StructDecl *optionSetDecl,
+ ValueDecl *valueDecl) {
auto &C = optionSetDecl->getASTContext();
auto optionSetType = optionSetDecl->getDeclaredTypeInContext();
- VarDecl *selfDecl = createSelfDecl(optionSetDecl, true);
+ VarDecl *selfDecl = createSelfDecl(optionSetDecl, /*staticMethod=*/false);
Pattern *selfParam = createTypedNamedPattern(selfDecl);
- Pattern *methodParam = TuplePattern::create(C, SourceLoc(),{},SourceLoc());
- methodParam->setType(TupleType::getEmpty(C));
- Pattern *params[] = {selfParam, methodParam};
- Identifier baseName = C.getIdentifier("convertFromNilLiteral");
-
- DeclName name(C, baseName, { });
- auto factoryDecl = FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None,
- SourceLoc(),
- name,
- SourceLoc(), nullptr, Type(), params,
- TypeLoc::withoutLoc(optionSetType),
- optionSetDecl);
-
- factoryDecl->setStatic();
- factoryDecl->setImplicit();
- factoryDecl->setAccessibility(Accessibility::Public);
+ VarDecl *nilDecl = new (C) ParamDecl(/*isLet=*/true, SourceLoc(),
+ C.Id_NilLiteral, SourceLoc(),
+ Identifier(),
+ TupleType::getEmpty(C),
+ optionSetDecl);
+ Pattern *nilParam = createTypedNamedPattern(nilDecl);
+ Pattern *methodParam = TuplePattern::create(C, SourceLoc(),
+ { TuplePatternElt(nilParam) },
+ SourceLoc());
+ methodParam->setType(ParenType::get(C, nilParam->getType()));
- Type factoryType = FunctionType::get(TupleType::getEmpty(C), optionSetType);
- factoryType = FunctionType::get(selfDecl->getType(), factoryType);
- factoryDecl->setType(factoryType);
- factoryDecl->setBodyResultType(optionSetType);
+ DeclName initName(C, C.Id_init, { C.Id_NilLiteral });
+ auto initDecl = new (C) ConstructorDecl(initName, SourceLoc(), OTK_None,
+ SourceLoc(), selfParam, methodParam,
+ nullptr, optionSetDecl);
+ initDecl->setImplicit();
+ initDecl->setAccessibility(Accessibility::Public);
+ Type metaType = MetatypeType::get(optionSetType);
+ Type paramType = TupleType::get({ TupleTypeElt(methodParam->getType(),
+ C.Id_NilLiteral) },
+ C);
+ Type fnType = FunctionType::get(paramType, optionSetType);
+ Type allocFnType = FunctionType::get(metaType, fnType);
+ Type initFnType = FunctionType::get(optionSetType, fnType);
+ initDecl->setType(allocFnType);
+ initDecl->setInitializerType(initFnType);
+
+ // Form the body of the initializer.
auto *ctorRef = new (C) DeclRefExpr(ConcreteDeclRef(optionSetDecl),
SourceLoc(), /*implicit*/ true);
auto *arg = TupleExpr::createEmpty(C, SourceLoc(), SourceLoc(),
/*implicit*/ true);
auto *ctorCall = new (C) CallExpr(ctorRef, arg, /*implicit*/ true);
- auto *ctorRet = new (C) ReturnStmt(SourceLoc(), ctorCall, /*implicit*/ true);
+
+ auto selfRef = new (C) DeclRefExpr(selfDecl, SourceLoc(), /*implicit*/ true,
+ /*UsesDirectPropertyAccess=*/false,
+ selfDecl->getType());
+
+ auto *assign = new (C) AssignExpr(selfRef, SourceLoc(), ctorCall,
+ /*implicit*/ true);
auto body = BraceStmt::create(C, SourceLoc(),
- ASTNode(ctorRet),
+ ASTNode(assign),
SourceLoc(),
/*implicit*/ true);
- factoryDecl->setBody(body);
+ initDecl->setBody(body);
// Add as an external definition.
- C.addedExternalDecl(factoryDecl);
+ C.addedExternalDecl(initDecl);
- return factoryDecl;
+ return initDecl;
}
// Build the default initializer for an option set.
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 0590c7ba59d..20fb3495f7f 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -1318,9 +1318,11 @@ namespace {
if (defaultType->isEqual(type))
type = defaultType;
}
-
+
+ DeclName initName(tc.Context, tc.Context.Id_init,
+ { tc.Context.Id_NilLiteral });
return convertLiteral(expr, type, expr->getType(), protocol,
- Identifier(), tc.Context.Id_ConvertFromNilLiteral,
+ Identifier(), initName,
nullptr, Identifier(),
Identifier(),
[] (Type type) -> bool {
diff --git a/stdlib/core/BridgeObjectiveC.swift b/stdlib/core/BridgeObjectiveC.swift
index 81c74aa28e6..3a65a459147 100644
--- a/stdlib/core/BridgeObjectiveC.swift
+++ b/stdlib/core/BridgeObjectiveC.swift
@@ -401,8 +401,8 @@ public struct AutoreleasingUnsafeMutablePointer
}
@transparent public
- static func convertFromNilLiteral() -> AutoreleasingUnsafeMutablePointer {
- return AutoreleasingUnsafeMutablePointer(_nilRawPointer)
+ init(nilLiteral: ()) {
+ value = _nilRawPointer
}
@transparent public
diff --git a/stdlib/core/CTypes.swift b/stdlib/core/CTypes.swift
index ae4ed85032f..573b82556ca 100644
--- a/stdlib/core/CTypes.swift
+++ b/stdlib/core/CTypes.swift
@@ -81,7 +81,7 @@ public struct COpaquePointer : Equatable, Hashable, NilLiteralConvertible {
@transparent
public init() {
- value = Builtin.inttoptr_Word(0.value)
+ value = _nilRawPointer
}
@transparent
@@ -133,8 +133,8 @@ public struct COpaquePointer : Equatable, Hashable, NilLiteralConvertible {
}
@transparent public
- static func convertFromNilLiteral() -> COpaquePointer {
- return COpaquePointer()
+ init(nilLiteral: ()) {
+ value = _nilRawPointer
}
}
@@ -168,8 +168,8 @@ public struct CFunctionPointer : Equatable, Hashable, NilLiteralConvertible {
}
@transparent public
- static func convertFromNilLiteral() -> CFunctionPointer {
- return CFunctionPointer()
+ init(nilLiteral: ()) {
+ value = COpaquePointer()
}
}
diff --git a/stdlib/core/CompilerProtocols.swift b/stdlib/core/CompilerProtocols.swift
index 8ee83cb9140..c9290c8eb3f 100644
--- a/stdlib/core/CompilerProtocols.swift
+++ b/stdlib/core/CompilerProtocols.swift
@@ -204,7 +204,7 @@ public protocol RawOptionSetType : _RawOptionSetType, BitwiseOperationsType,
/// Conforming to this protocol allows a type to be usable with the 'nil'
/// literal.
public protocol NilLiteralConvertible {
- class func convertFromNilLiteral() -> Self
+ init(nilLiteral: ())
}
public protocol _BuiltinIntegerLiteralConvertible {
diff --git a/stdlib/core/ImplicitlyUnwrappedOptional.swift b/stdlib/core/ImplicitlyUnwrappedOptional.swift
index 69a6866b180..481b3bdd745 100644
--- a/stdlib/core/ImplicitlyUnwrappedOptional.swift
+++ b/stdlib/core/ImplicitlyUnwrappedOptional.swift
@@ -34,8 +34,8 @@ public enum ImplicitlyUnwrappedOptional
// Make nil work with ImplicitlyUnwrappedOptional
@transparent public
- static func convertFromNilLiteral() -> ImplicitlyUnwrappedOptional {
- return .None
+ init(nilLiteral: ()) {
+ self = .None
}
/// Haskell's fmap, which was mis-named
diff --git a/stdlib/core/Optional.swift b/stdlib/core/Optional.swift
index a5fb9431170..434a99ea00f 100644
--- a/stdlib/core/Optional.swift
+++ b/stdlib/core/Optional.swift
@@ -37,8 +37,8 @@ public enum Optional : Reflectable, NilLiteralConvertible {
}
@transparent
- public static func convertFromNilLiteral() -> Optional {
- return .None
+ public init(nilLiteral: ()) {
+ self = .None
}
}
@@ -131,8 +131,7 @@ public func != (lhs: T?, rhs: T?) -> Bool {
// isn't equatable.
public struct _OptionalNilComparisonType : NilLiteralConvertible {
@transparent
- public static func convertFromNilLiteral() -> _OptionalNilComparisonType {
- return _OptionalNilComparisonType()
+ public init(nilLiteral: ()) {
}
}
@transparent public
diff --git a/stdlib/core/UnsafePointer.swift.gyb b/stdlib/core/UnsafePointer.swift.gyb
index 26a52ed9079..e7e2603f463 100644
--- a/stdlib/core/UnsafePointer.swift.gyb
+++ b/stdlib/core/UnsafePointer.swift.gyb
@@ -95,8 +95,8 @@ public struct ${Self}
// Make nil work with ${Self}.
@transparent public
- static func convertFromNilLiteral() -> ${Self} {
- return .null()
+ init(nilLiteral: ()) {
+ self = .null()
}
@transparent
diff --git a/stdlib/objc/ObjectiveC/ObjectiveC.swift b/stdlib/objc/ObjectiveC/ObjectiveC.swift
index 7aa92afa471..2977014a67c 100644
--- a/stdlib/objc/ObjectiveC/ObjectiveC.swift
+++ b/stdlib/objc/ObjectiveC/ObjectiveC.swift
@@ -121,8 +121,8 @@ public struct Selector : StringLiteralConvertible, NilLiteralConvertible {
}
@transparent public
- static func convertFromNilLiteral() -> Selector {
- return Selector()
+ init(nilLiteral: ()) {
+ ptr = nil
}
}
@@ -170,8 +170,8 @@ public struct NSZone : NilLiteralConvertible {
public init() { pointer = nil }
@transparent public
- static func convertFromNilLiteral() -> NSZone {
- return NSZone()
+ init(nilLiteral: ()) {
+ pointer = nil
}
}
diff --git a/test/IDE/Inputs/mock-sdk/Foo.annotated.txt b/test/IDE/Inputs/mock-sdk/Foo.annotated.txt
index 2627bd3d99d..edfd295f333 100644
--- a/test/IDE/Inputs/mock-sdk/Foo.annotated.txt
+++ b/test/IDE/Inputs/mock-sdk/Foo.annotated.txt
@@ -39,7 +39,7 @@ struct FooRuncingOptions : RawOptionSetType {
static var EnableMince: FooRuncingOptions { get }
static var EnableQuince: FooRuncingOptions { get }
static var allZeros: FooRuncingOptions { get }
- static func convertFromNilLiteral() -> FooRuncingOptions
+ init(nilLiteral _: ())
}
struct FooStruct1 {
var x: Int32
diff --git a/test/IDE/Inputs/mock-sdk/Foo.printed.recursive.txt b/test/IDE/Inputs/mock-sdk/Foo.printed.recursive.txt
index 2fc6e7d36e3..45ffdcb067d 100644
--- a/test/IDE/Inputs/mock-sdk/Foo.printed.recursive.txt
+++ b/test/IDE/Inputs/mock-sdk/Foo.printed.recursive.txt
@@ -39,7 +39,7 @@ struct FooRuncingOptions : RawOptionSetType {
static var EnableMince: FooRuncingOptions { get }
static var EnableQuince: FooRuncingOptions { get }
static var allZeros: FooRuncingOptions { get }
- static func convertFromNilLiteral() -> FooRuncingOptions
+ init(nilLiteral _: ())
}
struct FooStruct1 {
var x: Int32
diff --git a/test/IDE/Inputs/mock-sdk/Foo.printed.txt b/test/IDE/Inputs/mock-sdk/Foo.printed.txt
index 2f9e5d25f80..384bf31bdb1 100644
--- a/test/IDE/Inputs/mock-sdk/Foo.printed.txt
+++ b/test/IDE/Inputs/mock-sdk/Foo.printed.txt
@@ -52,7 +52,7 @@ struct FooRuncingOptions : RawOptionSetType {
static var EnableMince: FooRuncingOptions { get }
static var EnableQuince: FooRuncingOptions { get } /* But this is quince */
static var allZeros: FooRuncingOptions { get }
- static func convertFromNilLiteral() -> FooRuncingOptions
+ init(nilLiteral _: ())
}
struct FooStruct1 {
diff --git a/test/IDE/print_clang_decls.swift b/test/IDE/print_clang_decls.swift
index 841d6a58598..2c60af45069 100644
--- a/test/IDE/print_clang_decls.swift
+++ b/test/IDE/print_clang_decls.swift
@@ -79,7 +79,7 @@
// FOUNDATION-NEXT: {{^}} static var EnableMince: NSRuncingOptions { get }{{$}}
// FOUNDATION-NEXT: {{^}} static var EnableQuince: NSRuncingOptions { get }{{$}}
// FOUNDATION-NEXT: {{^}} static var allZeros: NSRuncingOptions { get }{{$}}
-// FOUNDATION-NEXT: {{^}} static func convertFromNilLiteral() -> NSRuncingOptions{{$}}
+// FOUNDATION-NEXT: {{^}} init(nilLiteral _: ()){{$}}
// FOUNDATION-NEXT: {{^}}}{{$}}
// FOUNDATION-LABEL: {{^}}/// Unavailable Global Functions{{$}}
diff --git a/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift b/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
index 259fa27a0d4..3f480647ecf 100644
--- a/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
+++ b/test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
@@ -62,8 +62,8 @@ public struct NSZone: NilLiteralConvertible {
public var pointer : COpaquePointer
@transparent public
- static func convertFromNilLiteral() -> NSZone {
- return NSZone(pointer: COpaquePointer())
+ init(nilLiteral: ()) {
+ pointer = COpaquePointer()
}
}