Skip to content

Commit

Permalink
[Sema] Emit a diagnostic when extending a protocol with a redundant r…
Browse files Browse the repository at this point in the history
…equirement (#20503)

* Emit a warning diagnostic if an extension contains a redundant requirement

* Updates diagnostic message and checks if the extension type is a protocol

* Updates indentation and extracts self type

* [ast] Updates diagnostic message

* [ast] fix indentation

* [ast] Change ':' to 'to' in 'protocol_extension_redundant_requirement'

* [sema] Adds protocol extension redundant requirement check

Moved from TypeCheckRequests to TypeCheckGeneric

* [ast] fix some crashes related to null ptrs, check self type before emitting a diagnostic, update tests

* [ast] renames 'owner' to 'ext'

* [sema] fix style

* [test] Add another test case for redundant requirement

Co-Authored-By: theblixguy <suyashsrijan@outlook.com>

* [test] fix failing test

The test was failing because A has already been declared as a typealias.
  • Loading branch information
theblixguy authored and harlanhaskins committed Nov 16, 2018
1 parent a728b26 commit 0d9f634
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ NOTE(profile_read_error,none,
ERROR(generic_signature_not_minimal,none,
"generic requirement '%0' is redundant in %1", (StringRef, StringRef))

WARNING(protocol_extension_redundant_requirement,none,
"requirement of '%1' to '%2' is redundant in an extension of '%0'",
(StringRef, StringRef, StringRef))

ERROR(attr_only_on_parameters, none,
"'%0' may only be used on parameters", (StringRef))

Expand Down
26 changes: 26 additions & 0 deletions lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ void checkGenericParamList(TypeChecker &tc,
RequirementRequest::visitRequirements(owner, resolution.getStage(),
[&](const Requirement &req, RequirementRepr *reqRepr) {
auto source = FloatingRequirementSource::forExplicit(reqRepr);

// If we're extending a protocol and adding a redundant requirement,
// for example, `extension Foo where Self: Foo`, then emit a
// diagnostic.

if (auto decl = owner.dc->getAsDecl()) {
if (auto extDecl = dyn_cast<ExtensionDecl>(decl)) {
auto extType = extDecl->getExtendedType();
auto extSelfType = extDecl->getSelfInterfaceType();
auto reqLHSType = req.getFirstType();
auto reqRHSType = req.getSecondType();

if (extType->isExistentialType() &&
reqLHSType->isEqual(extSelfType) &&
reqRHSType->isEqual(extType)) {

auto &ctx = extDecl->getASTContext();
ctx.Diags.diagnose(extDecl->getLoc(),
diag::protocol_extension_redundant_requirement,
extType->getString(),
extSelfType->getString(),
reqRHSType->getString());
}
}
}

builder->addRequirement(req, reqRepr, source, nullptr,
lookupDC->getParentModule());
return false;
Expand Down
17 changes: 17 additions & 0 deletions test/decl/ext/protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,23 @@ extension S1 {
}
}

// ----------------------------------------------------------------------------
// Protocol extensions with redundant requirements
// ----------------------------------------------------------------------------

protocol FooProtocol {}
extension FooProtocol where Self: FooProtocol {} // expected-warning {{requirement of 'Self' to 'FooProtocol' is redundant in an extension of 'FooProtocol'}}

protocol AnotherFooProtocol {}
protocol BazProtocol {}
extension AnotherFooProtocol where Self: BazProtocol, Self: AnotherFooProtocol {} // expected-warning {{requirement of 'Self' to 'AnotherFooProtocol' is redundant in an extension of 'AnotherFooProtocol'}}

protocol AnotherBazProtocol {
associatedtype BazValue
}

extension AnotherBazProtocol where BazValue: AnotherBazProtocol {} // ok, does not warn because BazValue is not Self

// ----------------------------------------------------------------------------
// Protocol extensions with additional requirements
// ----------------------------------------------------------------------------
Expand Down

0 comments on commit 0d9f634

Please sign in to comment.