Skip to content

[5.1] Sema: Protocol requirements cannot use opaque return types. #25586

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3611,6 +3611,10 @@ ERROR(unsupported_opaque_type,none,
ERROR(opaque_type_unsupported_pattern,none,
"'some' type can only be declared on a single property declaration", ())

ERROR(opaque_type_in_protocol_requirement,none,
"'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?",
())

// SIL
ERROR(opened_non_protocol,none,
"@opened cannot be applied to non-protocol type %0", (Type))
Expand Down
20 changes: 20 additions & 0 deletions lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,26 @@ static void revertDependentTypeLoc(TypeLoc &tl) {
Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
ValueDecl *originatingDecl,
OpaqueReturnTypeRepr *repr) {
// Protocol requirements can't have opaque return types.
//
// TODO: Maybe one day we could treat this as sugar for an associated type.
if (isa<ProtocolDecl>(originatingDecl->getDeclContext())
&& originatingDecl->isProtocolRequirement()) {

SourceLoc fixitLoc;
if (auto vd = dyn_cast<VarDecl>(originatingDecl)) {
fixitLoc = vd->getParentPatternBinding()->getStartLoc();
} else {
fixitLoc = originatingDecl->getStartLoc();
}

diagnose(repr->getLoc(), diag::opaque_type_in_protocol_requirement)
.fixItInsert(fixitLoc, "associatedtype <#AssocType#>\n")
.fixItReplace(repr->getSourceRange(), "<#AssocType#>");

return ErrorType::get(Context);
}

// If the decl already has an opaque type decl for its return type, use it.
if (auto existingDecl = originatingDecl->getOpaqueResultTypeDecl()) {
return existingDecl->getDeclaredInterfaceType();
Expand Down
13 changes: 12 additions & 1 deletion test/type/opaque.swift
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ struct OtherGeneric<X, Y, Z> {
var z: GenericWithOpaqueAssoc<Z>.Assoc
}


protocol P_51641323 {
associatedtype T

Expand All @@ -394,3 +393,15 @@ func rdar_51641323() {
// expected-note@-2 {{opaque return type declared here}}
}
}

// Protocol requirements cannot have opaque return types
protocol OpaqueProtocolRequirement {
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{20-26=<#AssocType#>}}
func method() -> some P

// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{13-19=<#AssocType#>}}
var prop: some P { get }

// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{18-24=<#AssocType#>}}
subscript() -> some P { get }
}