Skip to content

[Type checker] Provide actual ObjC runtime name in @NSKeyedArchiveLegacy Fix-Its. #9473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ DECL_ATTR(NSKeyedArchiveLegacy, NSKeyedArchiveLegacy,
/*Not serialized */ 68)

SIMPLE_DECL_ATTR(_staticInitializeObjCMetadata, StaticInitializeObjCMetadata,
OnClass | NotSerialized | LongAttribute | UserInaccessible,
OnClass | NotSerialized | LongAttribute | RejectByParser,
/*Not serialized */ 69)

SIMPLE_DECL_ATTR(NSKeyedArchiveSubclassesOnly,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ NOTE(unstable_mangled_name_add_nskeyedarchivelegacy,none,
"for compatibility with existing archives, use '@NSKeyedArchiveLegacy' "
"to record the Swift 3 mangled name", ())
NOTE(add_nskeyedarchivesubclassesonly_attr,none,
"generic classes should not be archived directly; "
"generic class %0 should not be archived directly; "
"add @NSKeyedArchiveSubclassesOnly "
"and only archive specific subclasses of this class", (Type))

Expand Down
9 changes: 8 additions & 1 deletion lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "swift/AST/AccessScope.h"
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
Expand Down Expand Up @@ -6048,13 +6049,19 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
auto insertionLoc =
classDecl->getAttributeInsertionLoc(/*forModifier=*/false);
if (isFixable) {
// Note: this is intentionally using the Swift 3 mangling,
// to provide compatibility with archives created in the Swift 3
// time frame.
Mangle::ASTMangler mangler;
diagnose(classDecl, diag::unstable_mangled_name_add_objc)
.fixItInsert(insertionLoc,
"@objc(<#Objective-C class name#>)");
diagnose(classDecl,
diag::unstable_mangled_name_add_nskeyedarchivelegacy)
.fixItInsert(insertionLoc,
"@NSKeyedArchiveLegacy(\"<#class archival name#>\")");
"@NSKeyedArchiveLegacy(\"" +
mangler.mangleObjCRuntimeName(classDecl) +
"\")");
} else {
diagnose(classDecl, diag::add_nskeyedarchivesubclassesonly_attr,
classDecl->getDeclaredInterfaceType())
Expand Down
20 changes: 12 additions & 8 deletions test/decl/protocol/conforms/nscoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ class CodingA : NSObject, NSCoding {
extension CodingA {
class NestedA : NSObject, NSCoding { // expected-error{{nested class 'CodingA.NestedA' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{for new classes, add '@objc' to specify a unique, prefixed Objective-C runtime name}}{{3-3=@objc(<#Objective-C class name#>)}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("<#class archival name#>")}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("_TtCC8nscoding7CodingA7NestedA")}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}

class NestedB : NSObject {
// expected-note@-1{{for new classes, add '@objc' to specify a unique, prefixed Objective-C runtime name}}{{3-3=@objc(<#Objective-C class name#>)}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("<#class archival name#>")}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("_TtCC8nscoding7CodingA7NestedB")}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}
Expand All @@ -51,14 +51,14 @@ extension CodingA.NestedD: NSCoding { // okay

// Generic classes
class CodingB<T> : NSObject, NSCoding { // expected-error{{generic class 'CodingB<T>' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{generic classes should not be archived directly}}{{1-1=@NSKeyedArchiveSubclassesOnly}}
// expected-note@-1{{generic class 'CodingB<T>' should not be archived directly}}{{1-1=@NSKeyedArchiveSubclassesOnly}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}

extension CodingB {
class NestedA : NSObject, NSCoding { // expected-error{{generic class 'CodingB<T>.NestedA' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{generic classes should not be archived directly}}{{3-3=@NSKeyedArchiveSubclassesOnly}}
// expected-note@-1{{generic class 'CodingB<T>.NestedA' should not be archived directly}}{{3-3=@NSKeyedArchiveSubclassesOnly}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}
Expand All @@ -67,15 +67,15 @@ extension CodingB {
// Fileprivate classes.
fileprivate class CodingC : NSObject, NSCoding { // expected-error{{fileprivate class 'CodingC' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{for new classes, add '@objc' to specify a unique, prefixed Objective-C runtime name}}{{1-1=@objc(<#Objective-C class name#>)}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{1-1=@NSKeyedArchiveLegacy("<#class archival name#>")}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{1-1=@NSKeyedArchiveLegacy("_TtC8nscodingP33_0B4E7641C0BD1F170280EEDD0D0C1F6C7CodingC")}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}

// Private classes
private class CodingD : NSObject, NSCoding { // expected-error{{private class 'CodingD' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{for new classes, add '@objc' to specify a unique, prefixed Objective-C runtime name}}{{1-1=@objc(<#Objective-C class name#>)}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{1-1=@NSKeyedArchiveLegacy("<#class archival name#>")}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{1-1=@NSKeyedArchiveLegacy("_TtC8nscodingP33_0B4E7641C0BD1F170280EEDD0D0C1F6C7CodingD")}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}
Expand All @@ -84,15 +84,15 @@ private class CodingD : NSObject, NSCoding { // expected-error{{private cl
func someFunction() {
class LocalCoding : NSObject, NSCoding { // expected-error{{local class 'LocalCoding' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{for new classes, add '@objc' to specify a unique, prefixed Objective-C runtime name}}{{3-3=@objc(<#Objective-C class name#>)}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("<#class archival name#>")}}
// expected-note@-2{{for compatibility with existing archives, use '@NSKeyedArchiveLegacy' to record the Swift 3 mangled name}}{{3-3=@NSKeyedArchiveLegacy("_TtCF8nscoding12someFunctionFT_T_L_11LocalCoding")}}
required init(coder: NSCoder) { }
func encode(coder: NSCoder) { }
}
}

// Inherited conformances.
class CodingE<T> : CodingB<T> { // expected-error{{generic class 'CodingE<T>' has an unstable name when archiving via 'NSCoding'}}
// expected-note@-1{{generic classes should not be archived directly}}{{1-1=@NSKeyedArchiveSubclassesOnly}}
// expected-note@-1{{generic class 'CodingE<T>' should not be archived directly}}{{1-1=@NSKeyedArchiveSubclassesOnly}}
required init(coder: NSCoder) { super.init(coder: coder) }
override func encode(coder: NSCoder) { }
}
Expand Down Expand Up @@ -139,6 +139,10 @@ extension CodingB {
// Inference of @_staticInitializeObjCMetadata.
class SubclassOfCodingE : CodingE<Int> { }

// But don't allow one to write @_staticInitializeObjCMetadata!
@_staticInitializeObjCMetadata // expected-error{{unknown attribute '_staticInitializeObjCMetadata'}}
class DontAllowStaticInits { }

// CHECK-NOT: class_decl "CodingA"{{.*}}@_staticInitializeObjCMetadata
// CHECK: class_decl "NestedA"{{.*}}@_staticInitializeObjCMetadata
// CHECK: class_decl "NestedC"{{.*}}@_staticInitializeObjCMetadata
Expand Down