diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index 5c366a71e2823..e0f4ec750d7f5 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -91,14 +91,8 @@ ProtocolDecl *DeclContext::getAsProtocolExtensionContext() const { GenericTypeParamType *DeclContext::getProtocolSelfType() const { assert(getAsProtocolOrProtocolExtensionContext() && "not a protocol"); - auto genericParams = getGenericParamsOfContext(); - - if (!genericParams) { - if (auto proto = dyn_cast(this)) { - getASTContext().getLazyResolver() - ->resolveDeclSignature(const_cast(proto)); - genericParams = getGenericParamsOfContext(); - } + if (auto proto = dyn_cast(this)) { + const_cast(proto)->createGenericParamsIfMissing(); } return getGenericParamsOfContext()->getParams().front() diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e6d38445a5dad..0a28e6a39e742 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -352,7 +352,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl, // Check all of the types listed in the inheritance clause. Type superclassTy; SourceRange superclassRange; - llvm::SmallDenseMap> inheritedTypes; + Optional> inheritedAnyObject; for (unsigned i = 0, n = inheritedClause.size(); i != n; ++i) { auto &inherited = inheritedClause[i]; @@ -368,36 +368,36 @@ void TypeChecker::checkInheritanceClause(Decl *decl, if (inheritedTy->hasError()) continue; - // Check whether we inherited from the same type twice. - auto knownPair = inheritedTypes.insert({ inheritedTy->getCanonicalType(), - {i, inherited.getSourceRange() }}); - if (knownPair.second == /*insertion failed*/false) { - auto knownIndex = knownPair.first->second.first; - auto knownRange = knownPair.first->second.second; - // If the duplicated type is 'AnyObject', check whether the first was - // written as 'class'. Downgrade the error to a warning in such cases - // for backward compatibility with Swift <= 4. - if (!Context.LangOpts.isSwiftVersionAtLeast(5) && - inheritedTy->isAnyObject() && - (isa(decl) || isa(decl)) && - Lexer::getTokenAtLocation(Context.SourceMgr, knownRange.Start) - .is(tok::kw_class)) { - SourceLoc classLoc = knownRange.Start; + // Check whether we inherited from 'AnyObject' twice. + // Other redundant-inheritance scenarios are checked below, the + // GenericSignatureBuilder (for protocol inheritance) or the + // ConformanceLookupTable (for protocol conformance). + if (inheritedTy->isAnyObject()) { + if (inheritedAnyObject) { + // If the first occurrence was written as 'class', downgrade the error + // to a warning in such cases + // for backward compatibility with Swift <= 4. + auto knownIndex = inheritedAnyObject->first; + auto knownRange = inheritedAnyObject->second; SourceRange removeRange = getRemovalRange(knownIndex); - - diagnose(classLoc, diag::duplicate_anyobject_class_inheritance) - .fixItRemoveChars(removeRange.Start, removeRange.End); - inherited.setInvalidType(Context); + if (!Context.LangOpts.isSwiftVersionAtLeast(5) && + (isa(decl) || isa(decl)) && + Lexer::getTokenAtLocation(Context.SourceMgr, knownRange.Start) + .is(tok::kw_class)) { + SourceLoc classLoc = knownRange.Start; + + diagnose(classLoc, diag::duplicate_anyobject_class_inheritance) + .fixItRemoveChars(removeRange.Start, removeRange.End); + } else { + diagnose(inherited.getSourceRange().Start, + diag::duplicate_inheritance, inheritedTy) + .fixItRemoveChars(removeRange.Start, removeRange.End); + } continue; } - auto removeRange = getRemovalRange(i); - diagnose(inherited.getSourceRange().Start, - diag::duplicate_inheritance, inheritedTy) - .fixItRemoveChars(removeRange.Start, removeRange.End) - .highlight(knownRange); - inherited.setInvalidType(Context); - continue; + // Note that we saw inheritance from 'AnyObject'. + inheritedAnyObject = { i, inherited.getSourceRange() }; } if (inheritedTy->isExistentialType()) { @@ -455,10 +455,16 @@ void TypeChecker::checkInheritanceClause(Decl *decl, if (isa(decl)) { // Check if we already had a raw type. if (superclassTy) { - diagnose(inherited.getSourceRange().Start, - diag::multiple_enum_raw_types, superclassTy, inheritedTy) - .highlight(superclassRange); - inherited.setInvalidType(Context); + if (superclassTy->isEqual(inheritedTy)) { + auto removeRange = getRemovalRange(i); + diagnose(inherited.getSourceRange().Start, + diag::duplicate_inheritance, inheritedTy) + .fixItRemoveChars(removeRange.Start, removeRange.End); + } else { + diagnose(inherited.getSourceRange().Start, + diag::multiple_enum_raw_types, superclassTy, inheritedTy) + .highlight(superclassRange); + } continue; } @@ -487,12 +493,19 @@ void TypeChecker::checkInheritanceClause(Decl *decl, if (superclassTy) { // FIXME: Check for shadowed protocol names, i.e., NSObject? - // Complain about multiple inheritance. - // Don't emit a Fix-It here. The user has to think harder about this. - diagnose(inherited.getSourceRange().Start, - diag::multiple_inheritance, superclassTy, inheritedTy) - .highlight(superclassRange); - inherited.setInvalidType(Context); + if (superclassTy->isEqual(inheritedTy)) { + // Duplicate superclass. + auto removeRange = getRemovalRange(i); + diagnose(inherited.getSourceRange().Start, + diag::duplicate_inheritance, inheritedTy) + .fixItRemoveChars(removeRange.Start, removeRange.End); + } else { + // Complain about multiple inheritance. + // Don't emit a Fix-It here. The user has to think harder about this. + diagnose(inherited.getSourceRange().Start, + diag::multiple_inheritance, superclassTy, inheritedTy) + .highlight(superclassRange); + } continue; } diff --git a/test/decl/inherit/inherit.swift b/test/decl/inherit/inherit.swift index d4122edbf328e..34cc23bce99a8 100644 --- a/test/decl/inherit/inherit.swift +++ b/test/decl/inherit/inherit.swift @@ -8,10 +8,9 @@ public protocol P1 { } class B : A, A { } // expected-error{{duplicate inheritance from 'A'}}{{12-15=}} // Duplicate inheritance from protocol -class B2 : P, P { } // expected-error{{duplicate inheritance from 'P'}}{{13-16=}} -// FIXME: These are unnecessary -// expected-note@-2 {{'B2' declares conformance to protocol 'P' here}} -// expected-error@-3 {{redundant conformance of 'B2' to protocol 'P'}} +class B2 : P, P { } +// expected-note@-1 {{'B2' declares conformance to protocol 'P' here}} +// expected-error@-2 {{redundant conformance of 'B2' to protocol 'P'}} // Multiple inheritance class C : B, A { } // expected-error{{multiple inheritance from classes 'B' and 'A'}} @@ -46,7 +45,7 @@ struct S2 : struct { } // expected-error{{expected type}} struct S3 : P, P & Q { } // expected-error {{redundant conformance of 'S3' to protocol 'P'}} // expected-error @-1 {{non-class type 'S3' cannot conform to class protocol 'Q'}} // expected-note @-2 {{'S3' declares conformance to protocol 'P' here}} -struct S4 : P, P { } // FIXME: expected-error {{duplicate inheritance from 'P'}} +struct S4 : P, P { } // expected-error@-1{{redundant conformance of 'S4' to protocol 'P'}} // expected-note@-2{{'S4' declares conformance to protocol 'P' here}} struct S6 : P & { } // expected-error {{expected identifier for type name}}