@@ -717,16 +717,11 @@ class ApplyClassifier {
717717 auto fnType = type->getAs <AnyFunctionType>();
718718 if (!fnType) return Classification::forInvalidCode ();
719719
720- Classification result;
721-
722- if (fnType->isAsync () || E->implicitlyAsync ())
723- result = Classification::forUnconditional (
724- EffectKind::Async,
725- PotentialEffectReason::forApply ());
726-
727- // If the function doesn't throw at all, we're done here.
728- if (!fnType->isThrowing ()) {
729- return result;
720+ // If the function doesn't have any effects, we're done here.
721+ if (!fnType->isThrowing () &&
722+ !fnType->isAsync () &&
723+ !E->implicitlyAsync ()) {
724+ return Classification ();
730725 }
731726
732727 // Decompose the application.
@@ -739,58 +734,86 @@ class ApplyClassifier {
739734 return Classification::forInvalidCode ();
740735 }
741736
742- // Handle rethrowing functions.
743- switch (fnRef.getPolymorphicEffectKind (EffectKind::Throws)) {
744- case PolymorphicEffectKind::ByConformance: {
745- auto substitutions = fnRef.getSubstitutions ();
746- for (auto conformanceRef : substitutions.getConformances ()) {
747- if (conformanceRef.hasEffect (EffectKind::Throws)) {
748- result.merge (Classification::forConditional (EffectKind::Throws,
749- PotentialEffectReason::forConformance ()));
750- return result;
737+ Classification result;
738+
739+ auto classifyApplyEffect = [&](EffectKind kind) {
740+ if (!fnType->hasEffect (kind) &&
741+ !(kind == EffectKind::Async &&
742+ E->implicitlyAsync ())) {
743+ return ;
744+ }
745+
746+ // Handle rethrowing and reasync functions.
747+ switch (fnRef.getPolymorphicEffectKind (kind)) {
748+ case PolymorphicEffectKind::ByConformance: {
749+ auto substitutions = fnRef.getSubstitutions ();
750+ for (auto conformanceRef : substitutions.getConformances ()) {
751+ if (conformanceRef.hasEffect (kind)) {
752+ result.merge (Classification::forConditional (kind,
753+ PotentialEffectReason::forConformance ()));
754+ return ;
755+ }
751756 }
757+
758+ // 'ByConformance' is a superset of 'ByClosure', so check for
759+ // closure arguments too.
760+ LLVM_FALLTHROUGH;
752761 }
753762
754- // 'ByConformance' is a superset of 'ByClosure', so check for
755- // closure arguments too.
756- LLVM_FALLTHROUGH;
757- }
763+ case PolymorphicEffectKind::ByClosure: {
764+ // We need to walk the original parameter types in parallel
765+ // because it only counts for rethrows/reasync purposes if it
766+ // lines up with a throws/async function parameter in the
767+ // original type.
768+ auto *origType = fnRef.getType ()->getAs <AnyFunctionType>();
769+ if (!origType) {
770+ result.merge (Classification::forInvalidCode ());
771+ return ;
772+ }
758773
759- case PolymorphicEffectKind::ByClosure: {
760- // We need to walk the original parameter types in parallel
761- // because it only counts for 'rethrows' purposes if it lines up
762- // with a throwing function parameter in the original type.
763- auto *origType = fnRef.getType ()->getAs <AnyFunctionType>();
764- if (!origType)
765- return Classification::forInvalidCode ();
774+ // Use the most significant result from the arguments.
775+ auto params = origType->getParams ();
776+ if (params.size () != args.size ()) {
777+ result.merge (Classification::forInvalidCode ());
778+ return ;
779+ }
766780
767- // Use the most significant result from the arguments.
768- auto params = origType->getParams ();
769- if (params.size () != args.size ())
770- return Classification::forInvalidCode ();
781+ for (unsigned i = 0 , e = params.size (); i < e; ++i) {
782+ result.merge (classifyArgument (args[i],
783+ params[i].getParameterType (),
784+ kind));
785+ }
771786
772- for (unsigned i = 0 , e = params.size (); i < e; ++i) {
773- result.merge (classifyArgument (args[i],
774- params[i].getParameterType (),
775- EffectKind::Throws));
787+ return ;
776788 }
777789
778- return result;
779- }
790+ case PolymorphicEffectKind::None:
791+ case PolymorphicEffectKind::Always:
792+ case PolymorphicEffectKind::Invalid:
793+ break ;
794+ }
780795
781- default :
782- break ;
783- }
796+ // Try to classify the implementation of functions that we have
797+ // local knowledge of.
798+ //
799+ // An autoclosure callee here only appears in a narrow case where
800+ // we're in the initializer of an 'async let'.
801+ if (fnRef.isAutoClosure ()) {
802+ result.merge (Classification::forUnconditional (
803+ kind, PotentialEffectReason::forApply ()));
804+ } else {
805+ result.merge (
806+ classifyFunctionBody (fnRef,
807+ PotentialEffectReason::forApply (),
808+ kind));
809+ assert (result.getConditionalKind (kind)
810+ != ConditionalEffectKind::None &&
811+ " body classification decided function had no effect?" );
812+ }
813+ };
784814
785- // Try to classify the implementation of functions that we have
786- // local knowledge of.
787- result.merge (
788- classifyFunctionBody (fnRef,
789- PotentialEffectReason::forApply (),
790- EffectKind::Throws));
791- assert (result.getConditionalKind (EffectKind::Throws)
792- != ConditionalEffectKind::None &&
793- " body classification decided function was no-throw" );
815+ classifyApplyEffect (EffectKind::Throws);
816+ classifyApplyEffect (EffectKind::Async);
794817
795818 return result;
796819 }
@@ -813,23 +836,12 @@ class ApplyClassifier {
813836 }
814837
815838private:
816- // / Classify a throwing function according to our local knowledge of
817- // / its implementation.
818- // /
819- // / For the most part, this only distinguishes between Throws and
820- // / RethrowingOnly. But it can return Invalid if a type-checking
821- // / failure prevents it from deciding that, and it can return None
822- // / if the function is an autoclosure that simply doesn't throw at all.
839+ // / Classify a throwing or async function according to our local
840+ // / knowledge of its implementation.
823841 Classification
824842 classifyFunctionBody (const AbstractFunction &fn,
825843 PotentialEffectReason reason,
826844 EffectKind kind) {
827- // If we're not checking a 'rethrows' context, we don't need to
828- // distinguish between 'throws' and 'rethrows'. But don't even
829- // trust 'throws' for autoclosures.
830- if (!getPolymorphicEffectDeclContext (kind) && !fn.isAutoClosure ())
831- return Classification::forUnconditional (kind, reason);
832-
833845 switch (fn.getKind ()) {
834846 case AbstractFunction::Opaque:
835847 return Classification::forUnconditional (kind, reason);
0 commit comments