|
17 | 17 | #include "TypeCheckAvailability.h" |
18 | 18 | #include "TypeCheckConcurrency.h" |
19 | 19 | #include "TypeCheckDecl.h" |
| 20 | +#include "TypeCheckEffects.h" |
20 | 21 | #include "TypeCheckObjC.h" |
21 | 22 | #include "TypeChecker.h" |
22 | 23 | #include "swift/AST/ASTVisitor.h" |
@@ -2036,16 +2037,53 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) { |
2036 | 2037 | diags.diagnose(base, diag::overridden_here); |
2037 | 2038 | } |
2038 | 2039 | } |
2039 | | - // If the overriding declaration is 'throws' but the base is not, |
2040 | | - // complain. Do the same for 'async' |
| 2040 | + |
| 2041 | + // Check effects. |
2041 | 2042 | if (auto overrideFn = dyn_cast<AbstractFunctionDecl>(override)) { |
2042 | | - if (overrideFn->hasThrows() && |
2043 | | - !cast<AbstractFunctionDecl>(base)->hasThrows()) { |
| 2043 | + // Determine the thrown errors in the base and override declarations. |
| 2044 | + auto baseFn = cast<AbstractFunctionDecl>(base); |
| 2045 | + Type overrideThrownError = |
| 2046 | + overrideFn->getEffectiveThrownErrorType().value_or(ctx.getNeverType()); |
| 2047 | + Type baseThrownError = |
| 2048 | + baseFn->getEffectiveThrownErrorType().value_or(ctx.getNeverType()); |
| 2049 | + |
| 2050 | + if (baseThrownError->hasTypeParameter()) { |
| 2051 | + auto subs = SubstitutionMap::getOverrideSubstitutions(base, override); |
| 2052 | + baseThrownError = baseThrownError.subst(subs); |
| 2053 | + baseThrownError = overrideFn->mapTypeIntoContext(baseThrownError); |
| 2054 | + } |
| 2055 | + |
| 2056 | + overrideThrownError = overrideFn->mapTypeIntoContext(overrideThrownError); |
| 2057 | + |
| 2058 | + // Check for a subtyping relationship. |
| 2059 | + switch (compareThrownErrorsForSubtyping( |
| 2060 | + overrideThrownError, baseThrownError, overrideFn)) { |
| 2061 | + case ThrownErrorSubtyping::DropsThrows: |
2044 | 2062 | diags.diagnose(override, diag::override_with_more_effects, |
2045 | 2063 | override->getDescriptiveKind(), "throwing"); |
2046 | 2064 | diags.diagnose(base, diag::overridden_here); |
| 2065 | + break; |
| 2066 | + |
| 2067 | + case ThrownErrorSubtyping::Mismatch: |
| 2068 | + diags.diagnose(override, diag::override_typed_throws, |
| 2069 | + override->getDescriptiveKind(), overrideThrownError, |
| 2070 | + baseThrownError); |
| 2071 | + diags.diagnose(base, diag::overridden_here); |
| 2072 | + break; |
| 2073 | + |
| 2074 | + case ThrownErrorSubtyping::ExactMatch: |
| 2075 | + case ThrownErrorSubtyping::Subtype: |
| 2076 | + // Proper subtyping. |
| 2077 | + break; |
| 2078 | + |
| 2079 | + case ThrownErrorSubtyping::Dependent: |
| 2080 | + // Only in already ill-formed code. |
| 2081 | + assert(ctx.Diags.hadAnyError()); |
| 2082 | + break; |
2047 | 2083 | } |
2048 | 2084 |
|
| 2085 | + // If the override is 'async' but the base declaration is not, we have a |
| 2086 | + // problem. |
2049 | 2087 | if (overrideFn->hasAsync() && |
2050 | 2088 | !cast<AbstractFunctionDecl>(base)->hasAsync()) { |
2051 | 2089 | diags.diagnose(override, diag::override_with_more_effects, |
|
0 commit comments