Skip to content

Commit 76ac2c7

Browse files
authored
Merge pull request #25586 from jckarter/no-opaque-type-in-protocol-5.1
[5.1] Sema: Protocol requirements cannot use opaque return types.
2 parents 356890b + c8ebda2 commit 76ac2c7

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,6 +3616,10 @@ ERROR(unsupported_opaque_type,none,
36163616
ERROR(opaque_type_unsupported_pattern,none,
36173617
"'some' type can only be declared on a single property declaration", ())
36183618

3619+
ERROR(opaque_type_in_protocol_requirement,none,
3620+
"'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?",
3621+
())
3622+
36193623
// SIL
36203624
ERROR(opened_non_protocol,none,
36213625
"@opened cannot be applied to non-protocol type %0", (Type))

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,26 @@ static void revertDependentTypeLoc(TypeLoc &tl) {
176176
Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
177177
ValueDecl *originatingDecl,
178178
OpaqueReturnTypeRepr *repr) {
179+
// Protocol requirements can't have opaque return types.
180+
//
181+
// TODO: Maybe one day we could treat this as sugar for an associated type.
182+
if (isa<ProtocolDecl>(originatingDecl->getDeclContext())
183+
&& originatingDecl->isProtocolRequirement()) {
184+
185+
SourceLoc fixitLoc;
186+
if (auto vd = dyn_cast<VarDecl>(originatingDecl)) {
187+
fixitLoc = vd->getParentPatternBinding()->getStartLoc();
188+
} else {
189+
fixitLoc = originatingDecl->getStartLoc();
190+
}
191+
192+
diagnose(repr->getLoc(), diag::opaque_type_in_protocol_requirement)
193+
.fixItInsert(fixitLoc, "associatedtype <#AssocType#>\n")
194+
.fixItReplace(repr->getSourceRange(), "<#AssocType#>");
195+
196+
return ErrorType::get(Context);
197+
}
198+
179199
// If the decl already has an opaque type decl for its return type, use it.
180200
if (auto existingDecl = originatingDecl->getOpaqueResultTypeDecl()) {
181201
return existingDecl->getDeclaredInterfaceType();

test/type/opaque.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,6 @@ struct OtherGeneric<X, Y, Z> {
380380
var z: GenericWithOpaqueAssoc<Z>.Assoc
381381
}
382382

383-
384383
protocol P_51641323 {
385384
associatedtype T
386385

@@ -394,3 +393,15 @@ func rdar_51641323() {
394393
// expected-note@-2 {{opaque return type declared here}}
395394
}
396395
}
396+
397+
// Protocol requirements cannot have opaque return types
398+
protocol OpaqueProtocolRequirement {
399+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{20-26=<#AssocType#>}}
400+
func method() -> some P
401+
402+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{13-19=<#AssocType#>}}
403+
var prop: some P { get }
404+
405+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{18-24=<#AssocType#>}}
406+
subscript() -> some P { get }
407+
}

0 commit comments

Comments
 (0)