1717
1818#include "CSDiagnostics.h"
1919#include "TypeCheckConcurrency.h"
20+ #include "TypeCheckEffects.h"
2021#include "swift/AST/ASTPrinter.h"
2122#include "swift/AST/Decl.h"
2223#include "swift/AST/ExistentialLayout.h"
@@ -2945,28 +2946,6 @@ bool ConstraintSystem::hasPreconcurrencyCallee(
29452946 return calleeOverload->choice.getDecl()->preconcurrency();
29462947}
29472948
2948- namespace {
2949- /// Classifies a thrown error kind as Never, a specific type, or 'any Error'.
2950- enum class ThrownErrorKind {
2951- Never,
2952- Specific,
2953- AnyError,
2954- };
2955-
2956- ThrownErrorKind getThrownErrorKind(Type type) {
2957- if (type->isNever())
2958- return ThrownErrorKind::Never;
2959-
2960- if (type->isExistentialType()) {
2961- Type anyError = type->getASTContext().getErrorExistentialType();
2962- if (anyError->isEqual(type))
2963- return ThrownErrorKind::AnyError;
2964- }
2965-
2966- return ThrownErrorKind::Specific;
2967- }
2968- }
2969-
29702949/// Match the throwing specifier of the two function types.
29712950static ConstraintSystem::TypeMatchResult
29722951matchFunctionThrowing(ConstraintSystem &cs,
@@ -2978,82 +2957,45 @@ matchFunctionThrowing(ConstraintSystem &cs,
29782957 // that throws error type E2 when E1 is a subtype of E2. For the purpose
29792958 // of this comparison, a non-throwing function has thrown error type 'Never',
29802959 // and an untyped throwing function has thrown error type 'any Error'.
2981- Type neverType = cs.getASTContext().getNeverType();
2982- Type thrownError1 = func1->getEffectiveThrownInterfaceType().value_or(neverType);
2983- Type thrownError2 = func2->getEffectiveThrownInterfaceType().value_or(neverType);
2984- if (!thrownError1 || !thrownError2 || thrownError1->isEqual(thrownError2))
2960+ Type thrownError1 = func1->getEffectiveThrownErrorTypeOrNever();
2961+ Type thrownError2 = func2->getEffectiveThrownErrorTypeOrNever();
2962+ if (!thrownError1 || !thrownError2)
29852963 return cs.getTypeMatchSuccess();
29862964
2987- auto thrownErrorKind1 = getThrownErrorKind(thrownError1);
2988- auto thrownErrorKind2 = getThrownErrorKind(thrownError2);
2989-
2990- bool mustUnify = false;
2991- bool dropThrows = false;
2992-
2993- switch (thrownErrorKind1) {
2994- case ThrownErrorKind::Specific:
2995- // If the specific thrown error contains no type variables and we're
2996- // going to try to convert it to \c Never, treat this as dropping throws.
2997- if (thrownErrorKind2 == ThrownErrorKind::Never &&
2998- !thrownError1->hasTypeVariable()) {
2999- dropThrows = true;
3000- } else {
3001- // We need to unify the thrown error types.
3002- mustUnify = true;
3003- }
3004- break;
3005-
3006- case ThrownErrorKind::Never:
3007- switch (thrownErrorKind2) {
3008- case ThrownErrorKind::Specific:
3009- // We need to unify the thrown error types.
3010- mustUnify = true;
3011- break;
3012-
3013- case ThrownErrorKind::Never:
3014- llvm_unreachable("The thrown error types should have been equal");
3015- break;
3016-
3017- case ThrownErrorKind::AnyError:
3018- // We have a subtype. If we're not allowed to do the subtype,
3019- // then we need to drop "throws".
3020- if (kind < ConstraintKind::Subtype)
3021- dropThrows = true;
3022- break;
3023- }
3024- break;
3025-
3026- case ThrownErrorKind::AnyError:
3027- switch (thrownErrorKind2) {
3028- case ThrownErrorKind::Specific:
3029- // We need to unify the thrown error types.
3030- mustUnify = true;
3031- break;
3032-
3033- case ThrownErrorKind::Never:
3034- // We're going to have to drop the "throws" entirely.
3035- dropThrows = true;
3036- break;
3037-
3038- case ThrownErrorKind::AnyError:
3039- llvm_unreachable("The thrown error types should have been equal");
3040- }
3041- break;
3042- }
3043-
3044- // If we know we need to drop 'throws', try it now.
3045- if (dropThrows) {
2965+ switch (compareThrownErrorsForSubtyping(thrownError1, thrownError2, cs.DC)) {
2966+ case ThrownErrorSubtyping::DropsThrows: {
2967+ // We need to drop 'throws' to make this work.
30462968 if (!cs.shouldAttemptFixes())
30472969 return cs.getTypeMatchFailure(locator);
30482970
30492971 auto *fix = DropThrowsAttribute::create(cs, func1, func2,
30502972 cs.getConstraintLocator(locator));
30512973 if (cs.recordFix(fix))
30522974 return cs.getTypeMatchFailure(locator);
2975+
2976+ return cs.getTypeMatchSuccess();
30532977 }
30542978
3055- // If we need to unify the thrown error types, do so now.
3056- if (mustUnify) {
2979+ case ThrownErrorSubtyping::ExactMatch:
2980+ return cs.getTypeMatchSuccess();
2981+
2982+ case ThrownErrorSubtyping::Subtype:
2983+ // We know this is going to work, but we might still need to generate a
2984+ // constraint if one of the error types involves type variables.
2985+ if (thrownError1->hasTypeVariable() || thrownError2->hasTypeVariable()) {
2986+ // Fall through to the dependent case.
2987+ } else if (kind < ConstraintKind::Subtype) {
2988+ // We aren't allowed to have a subtype, so fail here.
2989+ return cs.getTypeMatchFailure(locator);
2990+ } else {
2991+ // We have a subtype. All set!
2992+ return cs.getTypeMatchSuccess();
2993+ }
2994+ LLVM_FALLTHROUGH;
2995+
2996+ case ThrownErrorSubtyping::Dependent: {
2997+ // The presence of type variables in the thrown error types require that
2998+ // we generate a constraint to unify the thrown error types, so do so now.
30572999 ConstraintKind subKind = (kind < ConstraintKind::Subtype)
30583000 ? ConstraintKind::Equal
30593001 : ConstraintKind::Subtype;
@@ -3064,9 +3006,24 @@ matchFunctionThrowing(ConstraintSystem &cs,
30643006 locator.withPathElement(LocatorPathElt::ThrownErrorType()));
30653007 if (result == ConstraintSystem::SolutionKind::Error)
30663008 return cs.getTypeMatchFailure(locator);
3009+
3010+ return cs.getTypeMatchSuccess();
30673011 }
30683012
3069- return cs.getTypeMatchSuccess();
3013+ case ThrownErrorSubtyping::Mismatch: {
3014+ auto thrownErrorLocator = cs.getConstraintLocator(
3015+ locator.withPathElement(LocatorPathElt::ThrownErrorType()));
3016+ if (!cs.shouldAttemptFixes())
3017+ return cs.getTypeMatchFailure(thrownErrorLocator);
3018+
3019+ auto *fix = IgnoreThrownErrorMismatch::create(
3020+ cs, thrownError1, thrownError2, thrownErrorLocator);
3021+ if (cs.recordFix(fix))
3022+ return cs.getTypeMatchFailure(thrownErrorLocator);
3023+
3024+ return cs.getTypeMatchSuccess();
3025+ }
3026+ }
30703027}
30713028
30723029ConstraintSystem::TypeMatchResult
0 commit comments