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