Skip to content

Commit 83f86f5

Browse files
authored
Merge pull request #25581 from jckarter/no-opaque-type-in-protocol
Sema: Protocol requirements cannot use opaque return types.
2 parents 96ddf44 + 58a35f3 commit 83f86f5

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
@@ -3655,6 +3655,10 @@ ERROR(unsupported_opaque_type,none,
36553655
ERROR(opaque_type_unsupported_pattern,none,
36563656
"'some' type can only be declared on a single property declaration", ())
36573657

3658+
ERROR(opaque_type_in_protocol_requirement,none,
3659+
"'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?",
3660+
())
3661+
36583662
// SIL
36593663
ERROR(opened_non_protocol,none,
36603664
"@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
@@ -167,6 +167,26 @@ static void revertDependentTypeLoc(TypeLoc &tl) {
167167
Type TypeChecker::getOrCreateOpaqueResultType(TypeResolution resolution,
168168
ValueDecl *originatingDecl,
169169
OpaqueReturnTypeRepr *repr) {
170+
// Protocol requirements can't have opaque return types.
171+
//
172+
// TODO: Maybe one day we could treat this as sugar for an associated type.
173+
if (isa<ProtocolDecl>(originatingDecl->getDeclContext())
174+
&& originatingDecl->isProtocolRequirement()) {
175+
176+
SourceLoc fixitLoc;
177+
if (auto vd = dyn_cast<VarDecl>(originatingDecl)) {
178+
fixitLoc = vd->getParentPatternBinding()->getStartLoc();
179+
} else {
180+
fixitLoc = originatingDecl->getStartLoc();
181+
}
182+
183+
diagnose(repr->getLoc(), diag::opaque_type_in_protocol_requirement)
184+
.fixItInsert(fixitLoc, "associatedtype <#AssocType#>\n")
185+
.fixItReplace(repr->getSourceRange(), "<#AssocType#>");
186+
187+
return ErrorType::get(Context);
188+
}
189+
170190
// If the decl already has an opaque type decl for its return type, use it.
171191
if (auto existingDecl = originatingDecl->getOpaqueResultTypeDecl()) {
172192
return existingDecl->getDeclaredInterfaceType();

test/type/opaque.swift

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

369-
370369
protocol P_51641323 {
371370
associatedtype T
372371

@@ -380,3 +379,15 @@ func rdar_51641323() {
380379
// expected-note@-2 {{opaque return type declared here}}
381380
}
382381
}
382+
383+
// Protocol requirements cannot have opaque return types
384+
protocol OpaqueProtocolRequirement {
385+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{20-26=<#AssocType#>}}
386+
func method() -> some P
387+
388+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{13-19=<#AssocType#>}}
389+
var prop: some P { get }
390+
391+
// expected-error@+1 {{cannot be the return type of a protocol requirement}}{{3-3=associatedtype <#AssocType#>\n}}{{18-24=<#AssocType#>}}
392+
subscript() -> some P { get }
393+
}

0 commit comments

Comments
 (0)