@@ -305,6 +305,10 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
305
305
// / Get the property declaration for a behavior conformance, if this is one.
306
306
AbstractStorageDecl *getBehaviorDecl () const ;
307
307
308
+ // / Get any additional requirements that are required for this conformance to
309
+ // / be satisfied, if it is possible for them to be computed.
310
+ Optional<ArrayRef<Requirement>> getConditionalRequirementsIfAvailable () const ;
311
+
308
312
// / Get any additional requirements that are required for this conformance to
309
313
// / be satisfied.
310
314
ArrayRef<Requirement> getConditionalRequirements () const ;
@@ -380,7 +384,16 @@ class NormalProtocolConformance : public ProtocolConformance,
380
384
381
385
// / Any additional requirements that are required for this conformance to
382
386
// / apply, e.g. 'Something: Baz' in 'extension Foo: Bar where Something: Baz'.
383
- ArrayRef<Requirement> ConditionalRequirements;
387
+ mutable ArrayRef<Requirement> ConditionalRequirements;
388
+ enum class ConditionalRequirementsState {
389
+ Uncomputed,
390
+ Computing,
391
+ Complete,
392
+ };
393
+ // / The state of the ConditionalRequirements field: whether it has been
394
+ // / computed or not.
395
+ mutable ConditionalRequirementsState CRState =
396
+ ConditionalRequirementsState::Uncomputed;
384
397
385
398
// / The lazy member loader provides callbacks for populating imported and
386
399
// / deserialized conformances.
@@ -417,7 +430,7 @@ class NormalProtocolConformance : public ProtocolConformance,
417
430
418
431
void resolveLazyInfo () const ;
419
432
420
- void differenceAndStoreConditionalRequirements ();
433
+ void differenceAndStoreConditionalRequirements () const ;
421
434
422
435
public:
423
436
// / Get the protocol being conformed to.
@@ -437,11 +450,38 @@ class NormalProtocolConformance : public ProtocolConformance,
437
450
}
438
451
}
439
452
453
+ // / Get any additional requirements that are required for this conformance to
454
+ // / be satisfied if they can be computed.
455
+ // /
456
+ // / If \c computeIfPossible is false, this will not do the lazy computation of
457
+ // / the conditional requirements and will just query the current state. This
458
+ // / should almost certainly only be used for debugging purposes, prefer \c
459
+ // / getConditionalRequirementsIfAvailable (these are separate because
460
+ // / CONFORMANCE_SUBCLASS_DISPATCH does some type checks and a defaulted
461
+ // / parameter gets in the way of that).
462
+ Optional<ArrayRef<Requirement>>
463
+ getConditionalRequirementsIfAvailableOrCached (bool computeIfPossible) const {
464
+ if (computeIfPossible)
465
+ differenceAndStoreConditionalRequirements ();
466
+
467
+ if (CRState == ConditionalRequirementsState::Complete)
468
+ return ConditionalRequirements;
469
+
470
+ return None;
471
+ }
472
+ // / Get any additional requirements that are required for this conformance to
473
+ // / be satisfied if they can be computed.
474
+ Optional<ArrayRef<Requirement>>
475
+ getConditionalRequirementsIfAvailable () const {
476
+ return getConditionalRequirementsIfAvailableOrCached (
477
+ /* computeIfPossible=*/ true );
478
+ }
479
+
440
480
// / Get any additional requirements that are required for this conformance to
441
481
// / be satisfied, e.g. for Array<T>: Equatable, T: Equatable also needs
442
482
// / to be satisfied.
443
483
ArrayRef<Requirement> getConditionalRequirements () const {
444
- return ConditionalRequirements ;
484
+ return * getConditionalRequirementsIfAvailable () ;
445
485
}
446
486
447
487
// / Retrieve the state of this conformance.
@@ -660,14 +700,16 @@ class SpecializedProtocolConformance : public ProtocolConformance,
660
700
661
701
// / Any conditional requirements, in substituted form. (E.g. given Foo<T>: Bar
662
702
// / where T: Bar, Foo<Baz<U>> will include Baz<U>: Bar.)
663
- ArrayRef<Requirement> ConditionalRequirements;
703
+ mutable Optional< ArrayRef<Requirement> > ConditionalRequirements;
664
704
665
705
friend class ASTContext ;
666
706
667
707
SpecializedProtocolConformance (Type conformingType,
668
708
ProtocolConformance *genericConformance,
669
709
SubstitutionMap substitutions);
670
710
711
+ void computeConditionalRequirements () const ;
712
+
671
713
public:
672
714
// / Get the generic conformance from which this conformance was derived,
673
715
// / if there is one.
@@ -680,9 +722,29 @@ class SpecializedProtocolConformance : public ProtocolConformance,
680
722
SubstitutionMap getSubstitutionMap () const { return GenericSubstitutions; }
681
723
682
724
// / Get any requirements that must be satisfied for this conformance to apply.
683
- ArrayRef<Requirement> getConditionalRequirements () const {
725
+ // /
726
+ // / If \c computeIfPossible is false, this will not do the lazy computation of
727
+ // / the conditional requirements and will just query the current state. This
728
+ // / should almost certainly only be used for debugging purposes, prefer \c
729
+ // / getConditionalRequirementsIfAvailable (these are separate because
730
+ // / CONFORMANCE_SUBCLASS_DISPATCH does some type checks and a defaulted
731
+ // / parameter gets in the way of that).
732
+ Optional<ArrayRef<Requirement>>
733
+ getConditionalRequirementsIfAvailableOrCached (bool computeIfPossible) const {
734
+ if (computeIfPossible)
735
+ computeConditionalRequirements ();
684
736
return ConditionalRequirements;
685
737
}
738
+ Optional<ArrayRef<Requirement>>
739
+ getConditionalRequirementsIfAvailable () const {
740
+ return getConditionalRequirementsIfAvailableOrCached (
741
+ /* computeIfPossible=*/ true );
742
+ }
743
+
744
+ // / Get any requirements that must be satisfied for this conformance to apply.
745
+ ArrayRef<Requirement> getConditionalRequirements () const {
746
+ return *getConditionalRequirementsIfAvailable ();
747
+ }
686
748
687
749
// / Get the protocol being conformed to.
688
750
ProtocolDecl *getProtocol () const {
@@ -790,6 +852,12 @@ class InheritedProtocolConformance : public ProtocolConformance,
790
852
return InheritedConformance->getProtocol ();
791
853
}
792
854
855
+ // / Get any requirements that must be satisfied for this conformance to apply.
856
+ Optional<ArrayRef<Requirement>>
857
+ getConditionalRequirementsIfAvailable () const {
858
+ return InheritedConformance->getConditionalRequirementsIfAvailable ();
859
+ }
860
+
793
861
// / Get any requirements that must be satisfied for this conformance to apply.
794
862
ArrayRef<Requirement> getConditionalRequirements () const {
795
863
return InheritedConformance->getConditionalRequirements ();
0 commit comments