Skip to content

Commit d0aa22c

Browse files
committed
Allow "protocol P : class, AnyObject..." for Swift 4 compatibility.
Because of the way we modeled the 'class' constraint in Swift <= 4, we allowed both 'class' and 'AnyObject' to be specified on a protocol, even in Swift 4 when they became equivalent. Recent refactoring started rejecting such code; allow it now. Fixes rdar://problem/34496151.
1 parent 0c6b6f2 commit d0aa22c

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,8 @@ WARNING(override_swift3_objc_inference,none,
19361936
// Inheritance
19371937
ERROR(duplicate_inheritance,none,
19381938
"duplicate inheritance from %0", (Type))
1939+
WARNING(duplicate_anyobject_class_inheritance,none,
1940+
"redundant inheritance from 'AnyObject' and Swift 3 'class' keyword", ())
19391941
ERROR(multiple_inheritance,none,
19401942
"multiple inheritance from classes %0 and %1", (Type, Type))
19411943
ERROR(non_class_inheritance,none,

lib/Sema/TypeCheckDecl.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
440440
Type superclassTy;
441441
SourceRange superclassRange;
442442
llvm::SmallSetVector<ProtocolDecl *, 4> allProtocols;
443-
llvm::SmallDenseMap<CanType, SourceRange> inheritedTypes;
443+
llvm::SmallDenseMap<CanType, std::pair<unsigned, SourceRange>> inheritedTypes;
444444
addImplicitConformances(*this, decl, allProtocols);
445445
for (unsigned i = 0, n = inheritedClause.size(); i != n; ++i) {
446446
auto &inherited = inheritedClause[i];
@@ -475,15 +475,32 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
475475
CanType inheritedCanTy = inheritedTy->getCanonicalType();
476476
auto knownType = inheritedTypes.find(inheritedCanTy);
477477
if (knownType != inheritedTypes.end()) {
478+
// If the duplicated type is 'AnyObject', check whether the first was
479+
// written as 'class'. Downgrade the error to a warning in such cases
480+
// for backward compatibility.
481+
if (inheritedTy->isAnyObject() &&
482+
(isa<ProtocolDecl>(decl) || isa<AbstractTypeParamDecl>(decl)) &&
483+
Lexer::getTokenAtLocation(Context.SourceMgr,
484+
knownType->second.second.Start)
485+
.is(tok::kw_class)) {
486+
SourceLoc classLoc = knownType->second.second.Start;
487+
SourceRange removeRange = getRemovalRange(knownType->second.first);
488+
489+
diagnose(classLoc, diag::duplicate_anyobject_class_inheritance)
490+
.fixItRemoveChars(removeRange.Start, removeRange.End);
491+
inherited.setInvalidType(Context);
492+
continue;
493+
}
494+
478495
auto removeRange = getRemovalRange(i);
479496
diagnose(inherited.getSourceRange().Start,
480497
diag::duplicate_inheritance, inheritedTy)
481498
.fixItRemoveChars(removeRange.Start, removeRange.End)
482-
.highlight(knownType->second);
499+
.highlight(knownType->second.second);
483500
inherited.setInvalidType(Context);
484501
continue;
485502
}
486-
inheritedTypes[inheritedCanTy] = inherited.getSourceRange();
503+
inheritedTypes[inheritedCanTy] = { i, inherited.getSourceRange() };
487504

488505
// If this is a protocol or protocol composition type, record the
489506
// protocols.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 3
2+
// RUN: %target-typecheck-verify-swift -swift-version 4
3+
4+
protocol P : class, AnyObject { } // expected-warning{{redundant inheritance from 'AnyObject' and Swift 3 'class' keyword}}{{14-21=}}
5+
// expected-warning@-1{{redundant layout constraint 'Self' : 'AnyObject'}}
6+
// expected-note@-2{{layout constraint constraint 'Self' : 'AnyObject' written here}}

0 commit comments

Comments
 (0)