@@ -864,6 +864,11 @@ class Classification {
864864 }
865865 llvm_unreachable (" Bad effect kind" );
866866 }
867+ Type getThrownError () const {
868+ assert (ThrowKind == ConditionalEffectKind::Always ||
869+ ThrowKind == ConditionalEffectKind::Conditional);
870+ return ThrownError;
871+ }
867872 PotentialEffectReason getThrowReason () const {
868873 assert (ThrowKind == ConditionalEffectKind::Always ||
869874 ThrowKind == ConditionalEffectKind::Conditional);
@@ -1131,7 +1136,7 @@ class ApplyClassifier {
11311136 case EffectKind::Throws: {
11321137 FunctionThrowsClassifier classifier (*this );
11331138 expr->walk (classifier);
1134- return classifier.classification ;
1139+ return classifier.classification . onlyThrowing () ;
11351140 }
11361141 case EffectKind::Async: {
11371142 FunctionAsyncClassifier classifier (*this );
@@ -1143,6 +1148,23 @@ class ApplyClassifier {
11431148 llvm_unreachable (" Bad effect" );
11441149 }
11451150
1151+ // Classify a single statement without considering its enclosing context.
1152+ Classification classifyStmt (Stmt *stmt, EffectKind kind) {
1153+ switch (kind) {
1154+ case EffectKind::Throws: {
1155+ FunctionThrowsClassifier classifier (*this );
1156+ stmt->walk (classifier);
1157+ return classifier.classification .onlyThrowing ();
1158+ }
1159+ case EffectKind::Async: {
1160+ FunctionAsyncClassifier classifier (*this );
1161+ stmt->walk (classifier);
1162+ return Classification::forAsync (
1163+ classifier.AsyncKind , /* FIXME:*/ PotentialEffectReason::forApply ());
1164+ }
1165+ }
1166+ }
1167+
11461168private:
11471169 // / Classify a throwing or async function according to our local
11481170 // / knowledge of its implementation.
@@ -3242,6 +3264,26 @@ bool TypeChecker::canThrow(ASTContext &ctx, Expr *expr) {
32423264 ConditionalEffectKind::None;
32433265}
32443266
3267+ Type TypeChecker::catchErrorType (ASTContext &ctx, DoCatchStmt *stmt) {
3268+ // When typed throws is disabled, this is always "any Error".
3269+ // FIXME: When we distinguish "precise" typed throws from normal typed
3270+ // throws, we'll be able to compute a more narrow catch error type in some
3271+ // case, e.g., from a `try` but not a `throws`.
3272+ if (!ctx.LangOpts .hasFeature (Feature::TypedThrows))
3273+ return ctx.getErrorExistentialType ();
3274+
3275+ // Classify the throwing behavior of the "do" body.
3276+ ApplyClassifier classifier (ctx);
3277+ Classification classification = classifier.classifyStmt (
3278+ stmt->getBody (), EffectKind::Throws);
3279+
3280+ // If it doesn't throw at all, the type is Never.
3281+ if (!classification.hasThrows ())
3282+ return ctx.getNeverType ();
3283+
3284+ return classification.getThrownError ();
3285+ }
3286+
32453287Type TypeChecker::errorUnion (Type type1, Type type2) {
32463288 // If one type is NULL, return the other.
32473289 if (!type1)
0 commit comments