@@ -717,16 +717,11 @@ class ApplyClassifier {
717
717
auto fnType = type->getAs <AnyFunctionType>();
718
718
if (!fnType) return Classification::forInvalidCode ();
719
719
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 ();
730
725
}
731
726
732
727
// Decompose the application.
@@ -739,58 +734,86 @@ class ApplyClassifier {
739
734
return Classification::forInvalidCode ();
740
735
}
741
736
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
+ }
751
756
}
757
+
758
+ // 'ByConformance' is a superset of 'ByClosure', so check for
759
+ // closure arguments too.
760
+ LLVM_FALLTHROUGH;
752
761
}
753
762
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
+ }
758
773
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
+ }
766
780
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
+ }
771
786
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 ;
776
788
}
777
789
778
- return result;
779
- }
790
+ case PolymorphicEffectKind::None:
791
+ case PolymorphicEffectKind::Always:
792
+ case PolymorphicEffectKind::Invalid:
793
+ break ;
794
+ }
780
795
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
+ };
784
814
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);
794
817
795
818
return result;
796
819
}
@@ -813,23 +836,12 @@ class ApplyClassifier {
813
836
}
814
837
815
838
private:
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.
823
841
Classification
824
842
classifyFunctionBody (const AbstractFunction &fn,
825
843
PotentialEffectReason reason,
826
844
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
-
833
845
switch (fn.getKind ()) {
834
846
case AbstractFunction::Opaque:
835
847
return Classification::forUnconditional (kind, reason);
0 commit comments