Skip to content
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
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4244,6 +4244,9 @@ NOTE(opaque_type_underlying_type_candidate_here,none,
ERROR(opaque_type_self_referential_underlying_type,none,
"function opaque return type was inferred as %0, which defines the "
"opaque type in terms of itself", (Type))
ERROR(opaque_type_cannot_contain_dynamic_self,none,
"function with opaque return type cannot return "
"the covariant 'Self' type of a class", ())
ERROR(opaque_type_var_no_init,none,
"property declares an opaque return type, but has no initializer "
"expression from which to infer an underlying type", ())
Expand Down
14 changes: 10 additions & 4 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2815,20 +2815,26 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {

std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
if (auto underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(E)) {
auto key =
underlyingToOpaque->substitutions.getCanonical().getOpaqueValue();
auto subMap = underlyingToOpaque->substitutions;

auto key = subMap.getCanonical().getOpaqueValue();
auto isUnique = UniqueSignatures.insert(key).second;

auto candidate =
std::make_tuple(underlyingToOpaque->getSubExpr(),
underlyingToOpaque->substitutions, isUnique);
std::make_tuple(underlyingToOpaque->getSubExpr(), subMap, isUnique);

if (isSelfReferencing(candidate)) {
HasInvalidReturn = true;
return {false, nullptr};
}

if (subMap.hasDynamicSelf()) {
Ctx.Diags.diagnose(E->getLoc(),
diag::opaque_type_cannot_contain_dynamic_self);
HasInvalidReturn = true;
return {false, nullptr};
}

Candidates.push_back({CurrentAvailability, candidate});
return {false, E};
}
Expand Down
36 changes: 36 additions & 0 deletions test/type/opaque_return_dynamic_self.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// RUN: %target-typecheck-verify-swift -disable-availability-checking

protocol P {
init()
}

extension P {
static func opaqueProtocolExtensionFunc() -> some P { return Self() }
}

class C: P {
required init() {}

static func opaqueFunc1() -> some P {
return Self()
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
}

static func opaqueFunc2() -> some P {
return Self.opaqueProtocolExtensionFunc()
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
}

var opaqueProperty: some P {
return Self()
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
}

subscript() -> some P {
return Self()
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
}

var opaqueStoredProperty: some P = Self()
// expected-error@-1 {{covariant 'Self' type cannot be referenced from a stored property initializer}}
}