Skip to content

Commit 71aaba0

Browse files
authored
Merge pull request #11987 from DougGregor/protocol-class-anyobject-source-compat
2 parents de687ac + 6d9e921 commit 71aaba0

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-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: 21 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,33 @@ 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 with Swift <= 4.
481+
if (!Context.LangOpts.isSwiftVersionAtLeast(5) &&
482+
inheritedTy->isAnyObject() &&
483+
(isa<ProtocolDecl>(decl) || isa<AbstractTypeParamDecl>(decl)) &&
484+
Lexer::getTokenAtLocation(Context.SourceMgr,
485+
knownType->second.second.Start)
486+
.is(tok::kw_class)) {
487+
SourceLoc classLoc = knownType->second.second.Start;
488+
SourceRange removeRange = getRemovalRange(knownType->second.first);
489+
490+
diagnose(classLoc, diag::duplicate_anyobject_class_inheritance)
491+
.fixItRemoveChars(removeRange.Start, removeRange.End);
492+
inherited.setInvalidType(Context);
493+
continue;
494+
}
495+
478496
auto removeRange = getRemovalRange(i);
479497
diagnose(inherited.getSourceRange().Start,
480498
diag::duplicate_inheritance, inheritedTy)
481499
.fixItRemoveChars(removeRange.Start, removeRange.End)
482-
.highlight(knownType->second);
500+
.highlight(knownType->second.second);
483501
inherited.setInvalidType(Context);
484502
continue;
485503
}
486-
inheritedTypes[inheritedCanTy] = inherited.getSourceRange();
504+
inheritedTypes[inheritedCanTy] = { i, inherited.getSourceRange() };
487505

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

0 commit comments

Comments
 (0)