@@ -368,6 +368,114 @@ bool ConstraintSystem::containsIDEInspectionTarget(
368368 Context.SourceMgr );
369369}
370370
371+ void ConstraintSystem::recordPotentialThrowSite (
372+ PotentialThrowSite::Kind kind, Type type,
373+ ConstraintLocatorBuilder locator) {
374+ ASTContext &ctx = getASTContext ();
375+
376+ // Only record potential throw sites when typed throws is enabled.
377+ if (!ctx.LangOpts .hasFeature (Feature::TypedThrows))
378+ return ;
379+
380+ // Catch node location is determined by the source location.
381+ auto sourceLoc = locator.getAnchor ().getStartLoc ();
382+ if (!sourceLoc)
383+ return ;
384+
385+ auto catchNode = ASTScope::lookupCatchNode (DC->getParentModule (), sourceLoc);
386+ if (!catchNode)
387+ return ;
388+
389+ // If there is an explicit caught type for this node, we don't need to
390+ // record a potential throw site.
391+ if (Type explicitCaughtType = catchNode.getExplicitCaughtType (ctx))
392+ return ;
393+
394+ // do..catch statements without an explicit `throws` clause do infer
395+ // thrown types.
396+ if (auto doCatch = catchNode.dyn_cast <DoCatchStmt *>()) {
397+ potentialThrowSites.push_back (
398+ {catchNode,
399+ PotentialThrowSite{kind, type, getConstraintLocator (locator)}});
400+ return ;
401+ }
402+
403+ // Closures without an explicit `throws` clause, and which syntactically
404+ // appear that they can throw, do infer thrown types.
405+ auto closure = catchNode.get <ClosureExpr *>();
406+
407+ // Check whether the closure syntactically throws. If not, there is no
408+ // need to record a throw site.
409+ if (!closureEffects (closure).isThrowing ())
410+ return ;
411+
412+ potentialThrowSites.push_back (
413+ {catchNode,
414+ PotentialThrowSite{kind, type, getConstraintLocator (locator)}});
415+ }
416+
417+ Type ConstraintSystem::getCaughtErrorType (CatchNode catchNode) {
418+ ASTContext &ctx = getASTContext ();
419+
420+ // If there is an explicit caught type for this node, use it.
421+ if (Type explicitCaughtType = catchNode.getExplicitCaughtType (ctx)) {
422+ if (explicitCaughtType->hasTypeParameter ())
423+ explicitCaughtType = DC->mapTypeIntoContext (explicitCaughtType);
424+
425+ return explicitCaughtType;
426+ }
427+
428+ // Retrieve the thrown error type of a closure.
429+ // FIXME: This will need to change when we do inference of thrown error
430+ // types in closures.
431+ if (auto closure = catchNode.dyn_cast <ClosureExpr *>()) {
432+ return getClosureType (closure)->getEffectiveThrownErrorTypeOrNever ();
433+ }
434+
435+ // Handle inference of caught error types.
436+
437+ // Collect all of the potential throw sites for this catch node.
438+ SmallVector<PotentialThrowSite, 2 > throwSites;
439+ for (const auto &potentialThrowSite : potentialThrowSites) {
440+ if (potentialThrowSite.first == catchNode) {
441+ throwSites.push_back (potentialThrowSite.second );
442+ }
443+ }
444+
445+ Type caughtErrorType = ctx.getNeverType ();
446+ for (const auto &throwSite : throwSites) {
447+ Type type = simplifyType (throwSite.type );
448+
449+ Type thrownErrorType;
450+ switch (throwSite.kind ) {
451+ case PotentialThrowSite::Application: {
452+ auto fnType = type->castTo <AnyFunctionType>();
453+ thrownErrorType = fnType->getEffectiveThrownErrorTypeOrNever ();
454+ break ;
455+ }
456+
457+ case PotentialThrowSite::ExplicitThrow:
458+ case PotentialThrowSite::NonExhaustiveDoCatch:
459+ thrownErrorType = type;
460+ break ;
461+ }
462+
463+ // Perform the errorUnion() of the caught error type so far with the
464+ // thrown error type of this potential throw site.
465+ caughtErrorType = TypeChecker::errorUnion (
466+ caughtErrorType, thrownErrorType,
467+ [&](Type type) {
468+ return simplifyType (type);
469+ });
470+
471+ // If we ended up at 'any Error', we're done.
472+ if (caughtErrorType->isErrorExistentialType ())
473+ break ;
474+ }
475+
476+ return caughtErrorType;
477+ }
478+
371479ConstraintLocator *ConstraintSystem::getConstraintLocator (
372480 ASTNode anchor, ArrayRef<ConstraintLocator::PathElement> path) {
373481 auto summaryFlags = ConstraintLocator::getSummaryFlagsForPath (path);
0 commit comments