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() } }