Skip to content
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

[Sema] Emit a diagnostic when extending a protocol with a redundant requirement #20503

Merged
merged 12 commits into from
Nov 16, 2018
Merged
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,
theblixguy marked this conversation as resolved.
Show resolved Hide resolved
"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
17 changes: 17 additions & 0 deletions lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,23 @@ 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 extDecl = dyn_cast<ExtensionDecl>(owner.dc->getAsDecl())) {
auto ownerType = extDecl->getExtendedType();
auto selfType = req.getFirstType();
auto reqType = req.getSecondType();

if (ownerType->isExistentialType() && reqType->isEqual(ownerType)) {
theblixguy marked this conversation as resolved.
Show resolved Hide resolved
auto &ctx = extDecl->getASTContext();
ctx.Diags.diagnose(extDecl->getLoc(), diag::protocol_extension_redundant_requirement,
ownerType->getString(), selfType->getString(), reqType->getString());
}
}

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

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

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

protocol Bar {}
protocol Baz {}
extension Bar where Self: Baz {} // ok
extension Bar where Self: Bar, Self: Baz {} // expected-warning {{requirement of 'Self': 'Bar' is redundant in an extension of 'Bar'}}

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