@@ -2945,23 +2945,139 @@ bool ConstraintSystem::hasPreconcurrencyCallee(
29452945 return calleeOverload->choice.getDecl()->preconcurrency();
29462946}
29472947
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+
2970+ /// Match the throwing specifier of the two function types.
2971+ static ConstraintSystem::TypeMatchResult
2972+ matchFunctionThrowing(ConstraintSystem &cs,
2973+ FunctionType *func1, FunctionType *func2,
2974+ ConstraintKind kind,
2975+ ConstraintSystem::TypeMatchOptions flags,
2976+ ConstraintLocatorBuilder locator) {
2977+ // A function type that throws the error type E1 is a subtype of a function
2978+ // that throws error type E2 when E1 is a subtype of E2. For the purpose
2979+ // of this comparison, a non-throwing function has thrown error type 'Never',
2980+ // 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))
2985+ return cs.getTypeMatchSuccess();
2986+
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) {
3046+ if (!cs.shouldAttemptFixes())
3047+ return cs.getTypeMatchFailure(locator);
3048+
3049+ auto *fix = DropThrowsAttribute::create(cs, func1, func2,
3050+ cs.getConstraintLocator(locator));
3051+ if (cs.recordFix(fix))
3052+ return cs.getTypeMatchFailure(locator);
3053+ }
3054+
3055+ // If we need to unify the thrown error types, do so now.
3056+ if (mustUnify) {
3057+ ConstraintKind subKind = (kind < ConstraintKind::Subtype)
3058+ ? ConstraintKind::Equal
3059+ : ConstraintKind::Subtype;
3060+ const auto subflags = getDefaultDecompositionOptions(flags);
3061+ auto result = cs.matchTypes(
3062+ thrownError1, thrownError2,
3063+ subKind, subflags,
3064+ locator.withPathElement(LocatorPathElt::ThrownErrorType()));
3065+ if (result == ConstraintSystem::SolutionKind::Error)
3066+ return cs.getTypeMatchFailure(locator);
3067+ }
3068+
3069+ return cs.getTypeMatchSuccess();
3070+ }
3071+
29483072ConstraintSystem::TypeMatchResult
29493073ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
29503074 ConstraintKind kind, TypeMatchOptions flags,
29513075 ConstraintLocatorBuilder locator) {
2952- // A non-throwing function can be a subtype of a throwing function.
2953- if (func1->isThrowing() != func2->isThrowing()) {
2954- // Cannot drop 'throws'.
2955- if (func1->isThrowing() || kind < ConstraintKind::Subtype) {
2956- if (!shouldAttemptFixes())
2957- return getTypeMatchFailure(locator);
2958-
2959- auto *fix = DropThrowsAttribute::create(*this, func1, func2,
2960- getConstraintLocator(locator));
2961- if (recordFix(fix))
2962- return getTypeMatchFailure(locator);
2963- }
2964- }
3076+ // Match the 'throws' effect.
3077+ TypeMatchResult throwsResult =
3078+ matchFunctionThrowing(*this, func1, func2, kind, flags, locator);
3079+ if (throwsResult.isFailure())
3080+ return throwsResult;
29653081
29663082 // A synchronous function can be a subtype of an 'async' function.
29673083 if (func1->isAsync() != func2->isAsync()) {
@@ -5152,6 +5268,13 @@ bool ConstraintSystem::repairFailures(
51525268 getConstraintLocator(locator)))
51535269 return true;
51545270
5271+ if (locator.endsWith<LocatorPathElt::ThrownErrorType>()) {
5272+ conversionsOrFixes.push_back(
5273+ IgnoreThrownErrorMismatch::create(*this, lhs, rhs,
5274+ getConstraintLocator(locator)));
5275+ return true;
5276+ }
5277+
51555278 if (path.empty()) {
51565279 if (!anchor)
51575280 return false;
@@ -15002,6 +15125,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1500215125 case FixKind::IgnoreGenericSpecializationArityMismatch: {
1500315126 return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
1500415127 }
15128+ case FixKind::IgnoreThrownErrorMismatch: {
15129+ return recordFix(fix, 2) ? SolutionKind::Error : SolutionKind::Solved;
15130+ }
1500515131 case FixKind::IgnoreInvalidASTNode: {
1500615132 return recordFix(fix, 10) ? SolutionKind::Error : SolutionKind::Solved;
1500715133 }
0 commit comments