|
18 | 18 | #include "MiscDiagnostics.h"
|
19 | 19 | #include "TypeCheckDistributed.h"
|
20 | 20 | #include "TypeCheckInvertible.h"
|
| 21 | +#include "TypeCheckProtocol.h" |
21 | 22 | #include "TypeCheckType.h"
|
22 | 23 | #include "TypeChecker.h"
|
23 | 24 | #include "swift/AST/ASTWalker.h"
|
@@ -3175,6 +3176,18 @@ namespace {
|
3175 | 3176 | checkDefaultArgument(defaultArg);
|
3176 | 3177 | }
|
3177 | 3178 |
|
| 3179 | + if (auto erasureExpr = dyn_cast<ErasureExpr>(expr)) { |
| 3180 | + checkIsolatedConformancesInContext( |
| 3181 | + erasureExpr->getConformances(), erasureExpr->getLoc(), |
| 3182 | + getDeclContext()); |
| 3183 | + } |
| 3184 | + |
| 3185 | + if (auto *underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(expr)) { |
| 3186 | + checkIsolatedConformancesInContext( |
| 3187 | + underlyingToOpaque->substitutions, underlyingToOpaque->getLoc(), |
| 3188 | + getDeclContext()); |
| 3189 | + } |
| 3190 | + |
3178 | 3191 | return Action::Continue(expr);
|
3179 | 3192 | }
|
3180 | 3193 |
|
@@ -4282,6 +4295,9 @@ namespace {
|
4282 | 4295 | if (!declRef)
|
4283 | 4296 | return false;
|
4284 | 4297 |
|
| 4298 | + // Make sure isolated conformances are formed in the right context. |
| 4299 | + checkIsolatedConformancesInContext(declRef, loc, getDeclContext()); |
| 4300 | + |
4285 | 4301 | auto decl = declRef.getDecl();
|
4286 | 4302 |
|
4287 | 4303 | // If this declaration is a callee from the enclosing application,
|
@@ -7684,3 +7700,99 @@ ActorIsolation swift::getConformanceIsolation(ProtocolConformance *conformance)
|
7684 | 7700 |
|
7685 | 7701 | return getActorIsolation(nominal);
|
7686 | 7702 | }
|
| 7703 | + |
| 7704 | +namespace { |
| 7705 | + /// Identifies isolated conformances whose isolation differs from the |
| 7706 | + /// context's isolation. |
| 7707 | + class MismatchedIsolatedConformances { |
| 7708 | + llvm::TinyPtrVector<ProtocolConformance *> badIsolatedConformances; |
| 7709 | + DeclContext *fromDC; |
| 7710 | + mutable std::optional<ActorIsolation> fromIsolation; |
| 7711 | + |
| 7712 | + public: |
| 7713 | + MismatchedIsolatedConformances(const DeclContext *fromDC) |
| 7714 | + : fromDC(const_cast<DeclContext *>(fromDC)) { } |
| 7715 | + |
| 7716 | + ActorIsolation getContextIsolation() const { |
| 7717 | + if (!fromIsolation) |
| 7718 | + fromIsolation = getActorIsolationOfContext(fromDC); |
| 7719 | + |
| 7720 | + return *fromIsolation; |
| 7721 | + } |
| 7722 | + |
| 7723 | + ArrayRef<ProtocolConformance *> getBadIsolatedConformances() const { |
| 7724 | + return badIsolatedConformances; |
| 7725 | + } |
| 7726 | + |
| 7727 | + explicit operator bool() const { return !badIsolatedConformances.empty(); } |
| 7728 | + |
| 7729 | + bool operator()(ProtocolConformanceRef conformance) { |
| 7730 | + if (conformance.isAbstract() || conformance.isPack()) |
| 7731 | + return false; |
| 7732 | + |
| 7733 | + auto concrete = conformance.getConcrete(); |
| 7734 | + auto normal = dyn_cast<NormalProtocolConformance>( |
| 7735 | + concrete->getRootConformance()); |
| 7736 | + if (!normal) |
| 7737 | + return false; |
| 7738 | + |
| 7739 | + if (!normal->isIsolated()) |
| 7740 | + return false; |
| 7741 | + |
| 7742 | + auto conformanceIsolation = getConformanceIsolation(concrete); |
| 7743 | + if (conformanceIsolation == getContextIsolation()) |
| 7744 | + return true; |
| 7745 | + |
| 7746 | + badIsolatedConformances.push_back(concrete); |
| 7747 | + return false; |
| 7748 | + } |
| 7749 | + |
| 7750 | + /// If there were any bad isolated conformances, diagnose them and return |
| 7751 | + /// true. Otherwise, returns false. |
| 7752 | + bool diagnose(SourceLoc loc) const { |
| 7753 | + if (badIsolatedConformances.empty()) |
| 7754 | + return false; |
| 7755 | + |
| 7756 | + ASTContext &ctx = fromDC->getASTContext(); |
| 7757 | + auto firstConformance = badIsolatedConformances.front(); |
| 7758 | + ctx.Diags.diagnose( |
| 7759 | + loc, diag::isolated_conformance_wrong_domain, |
| 7760 | + getConformanceIsolation(firstConformance), |
| 7761 | + firstConformance->getType(), |
| 7762 | + firstConformance->getProtocol()->getName(), |
| 7763 | + getContextIsolation()); |
| 7764 | + return true; |
| 7765 | + } |
| 7766 | + }; |
| 7767 | + |
| 7768 | +} |
| 7769 | + |
| 7770 | +bool swift::checkIsolatedConformancesInContext( |
| 7771 | + ConcreteDeclRef declRef, SourceLoc loc, const DeclContext *dc) { |
| 7772 | + MismatchedIsolatedConformances mismatched(dc); |
| 7773 | + forEachConformance(declRef, mismatched); |
| 7774 | + return mismatched.diagnose(loc); |
| 7775 | +} |
| 7776 | + |
| 7777 | +bool swift::checkIsolatedConformancesInContext( |
| 7778 | + ArrayRef<ProtocolConformanceRef> conformances, SourceLoc loc, |
| 7779 | + const DeclContext *dc) { |
| 7780 | + MismatchedIsolatedConformances mismatched(dc); |
| 7781 | + for (auto conformance: conformances) |
| 7782 | + forEachConformance(conformance, mismatched); |
| 7783 | + return mismatched.diagnose(loc); |
| 7784 | +} |
| 7785 | + |
| 7786 | +bool swift::checkIsolatedConformancesInContext( |
| 7787 | + SubstitutionMap subs, SourceLoc loc, const DeclContext *dc) { |
| 7788 | + MismatchedIsolatedConformances mismatched(dc); |
| 7789 | + forEachConformance(subs, mismatched); |
| 7790 | + return mismatched.diagnose(loc); |
| 7791 | +} |
| 7792 | + |
| 7793 | +bool swift::checkIsolatedConformancesInContext( |
| 7794 | + Type type, SourceLoc loc, const DeclContext *dc) { |
| 7795 | + MismatchedIsolatedConformances mismatched(dc); |
| 7796 | + forEachConformance(type, mismatched); |
| 7797 | + return mismatched.diagnose(loc); |
| 7798 | +} |
0 commit comments