@@ -2967,101 +2967,118 @@ namespace {
2967
2967
}
2968
2968
}
2969
2969
2970
- ConstraintSystem::TypeMatchResult
2971
- ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
2972
- ConstraintKind kind, TypeMatchOptions flags,
2973
- ConstraintLocatorBuilder locator) {
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) {
2974
2977
// A function type that throws the error type E1 is a subtype of a function
2975
2978
// that throws error type E2 when E1 is a subtype of E2. For the purpose
2976
2979
// of this comparison, a non-throwing function has thrown error type 'Never',
2977
2980
// and an untyped throwing function has thrown error type 'any Error'.
2978
- Type neverType = getASTContext().getNeverType();
2981
+ Type neverType = cs. getASTContext().getNeverType();
2979
2982
Type thrownError1 = func1->getEffectiveThrownInterfaceType().value_or(neverType);
2980
2983
Type thrownError2 = func2->getEffectiveThrownInterfaceType().value_or(neverType);
2981
- if (thrownError1 && thrownError2 && !thrownError1->isEqual(thrownError2)) {
2982
- auto thrownErrorKind1 = getThrownErrorKind(thrownError1);
2983
- auto thrownErrorKind2 = getThrownErrorKind(thrownError2);
2984
-
2985
- bool mustUnify = false;
2986
- bool dropThrows = false;
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;
2987
3005
2988
- switch (thrownErrorKind1) {
3006
+ case ThrownErrorKind::Never:
3007
+ switch (thrownErrorKind2) {
2989
3008
case ThrownErrorKind::Specific:
2990
- // If the specific thrown error contains no type variables and we're
2991
- // going to try to convert it to \c Never, treat this as dropping throws.
2992
- if (thrownErrorKind2 == ThrownErrorKind::Never &&
2993
- !thrownError1->hasTypeVariable()) {
2994
- dropThrows = true;
2995
- } else {
2996
- // We need to unify the thrown error types.
2997
- mustUnify = true;
2998
- }
3009
+ // We need to unify the thrown error types.
3010
+ mustUnify = true;
2999
3011
break;
3000
3012
3001
3013
case ThrownErrorKind::Never:
3002
- switch (thrownErrorKind2) {
3003
- case ThrownErrorKind::Specific:
3004
- // We need to unify the thrown error types.
3005
- mustUnify = true;
3006
- break;
3007
-
3008
- case ThrownErrorKind::Never:
3009
- llvm_unreachable("The thrown error types should have been equal");
3010
- break;
3011
-
3012
- case ThrownErrorKind::AnyError:
3013
- // We have a subtype. If we're not allowed to do the subtype,
3014
- // then we need to drop "throws".
3015
- if (kind < ConstraintKind::Subtype)
3016
- dropThrows = true;
3017
- break;
3018
- }
3014
+ llvm_unreachable("The thrown error types should have been equal");
3019
3015
break;
3020
3016
3021
3017
case ThrownErrorKind::AnyError:
3022
- switch (thrownErrorKind2) {
3023
- case ThrownErrorKind::Specific:
3024
- // We need to unify the thrown error types.
3025
- mustUnify = true;
3026
- break;
3027
-
3028
- case ThrownErrorKind::Never:
3029
- // We're going to have to drop the "throws" entirely.
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)
3030
3021
dropThrows = true;
3031
- break;
3032
-
3033
- case ThrownErrorKind::AnyError:
3034
- llvm_unreachable("The thrown error types should have been equal");
3035
- }
3036
3022
break;
3037
3023
}
3024
+ break;
3038
3025
3039
- // If we know we need to drop 'throws', try it now.
3040
- if (dropThrows) {
3041
- if (!shouldAttemptFixes())
3042
- return getTypeMatchFailure(locator);
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;
3043
3032
3044
- auto *fix = DropThrowsAttribute::create(*this, func1, func2,
3045
- getConstraintLocator(locator));
3046
- if (recordFix(fix))
3047
- return getTypeMatchFailure(locator);
3048
- }
3033
+ case ThrownErrorKind::Never:
3034
+ // We're going to have to drop the "throws" entirely.
3035
+ dropThrows = true;
3036
+ break;
3049
3037
3050
- // If we need to unify the thrown error types, do so now.
3051
- if (mustUnify) {
3052
- ConstraintKind subKind = (kind < ConstraintKind::Subtype)
3053
- ? ConstraintKind::Equal
3054
- : ConstraintKind::Subtype;
3055
- const auto subflags = getDefaultDecompositionOptions(flags);
3056
- auto result = matchTypes(
3057
- thrownError1, thrownError2,
3058
- subKind, subflags,
3059
- locator.withPathElement(LocatorPathElt::ThrownErrorType()));
3060
- if (result == SolutionKind::Error)
3061
- return getTypeMatchFailure(locator);
3038
+ case ThrownErrorKind::AnyError:
3039
+ llvm_unreachable("The thrown error types should have been equal");
3062
3040
}
3041
+ break;
3063
3042
}
3064
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
+
3072
+ ConstraintSystem::TypeMatchResult
3073
+ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
3074
+ ConstraintKind kind, TypeMatchOptions flags,
3075
+ ConstraintLocatorBuilder locator) {
3076
+ // Match the 'throws' effect.
3077
+ TypeMatchResult throwsResult =
3078
+ matchFunctionThrowing(*this, func1, func2, kind, flags, locator);
3079
+ if (throwsResult.isFailure())
3080
+ return throwsResult;
3081
+
3065
3082
// A synchronous function can be a subtype of an 'async' function.
3066
3083
if (func1->isAsync() != func2->isAsync()) {
3067
3084
// Cannot drop 'async'.
@@ -15105,10 +15122,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
15105
15122
case FixKind::AllowAssociatedValueMismatch:
15106
15123
case FixKind::GenericArgumentsMismatch:
15107
15124
case FixKind::AllowConcreteTypeSpecialization:
15108
- case FixKind::IgnoreThrownErrorMismatch:
15109
15125
case FixKind::IgnoreGenericSpecializationArityMismatch: {
15110
15126
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
15111
15127
}
15128
+ case FixKind::IgnoreThrownErrorMismatch: {
15129
+ return recordFix(fix, 2) ? SolutionKind::Error : SolutionKind::Solved;
15130
+ }
15112
15131
case FixKind::IgnoreInvalidASTNode: {
15113
15132
return recordFix(fix, 10) ? SolutionKind::Error : SolutionKind::Solved;
15114
15133
}
0 commit comments