@@ -5463,8 +5463,8 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
5463
5463
// If this is a convenience initializer (i.e. one that calls
5464
5464
// self.init), then let properties are never mutable in it. They are
5465
5465
// only mutable in designated initializers.
5466
- if ( CD->getDelegatingOrChainedInitKind (nullptr ) ==
5467
- ConstructorDecl:: BodyInitKind::Delegating)
5466
+ auto initKindAndExpr = CD->getDelegatingOrChainedInitKind ();
5467
+ if (initKindAndExpr. initKind == BodyInitKind::Delegating)
5468
5468
return false ;
5469
5469
5470
5470
return true ;
@@ -7522,7 +7522,6 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
7522
7522
if (BodyParams)
7523
7523
setParameters (BodyParams);
7524
7524
7525
- Bits.ConstructorDecl .ComputedBodyInitKind = 0 ;
7526
7525
Bits.ConstructorDecl .HasStubImplementation = 0 ;
7527
7526
Bits.ConstructorDecl .Failable = Failable;
7528
7527
@@ -7750,169 +7749,17 @@ CtorInitializerKind ConstructorDecl::getInitKind() const {
7750
7749
CtorInitializerKind::Designated);
7751
7750
}
7752
7751
7753
- ConstructorDecl::BodyInitKind
7754
- ConstructorDecl::getDelegatingOrChainedInitKind (DiagnosticEngine *diags,
7755
- ApplyExpr **init) const {
7752
+ BodyInitKindAndExpr
7753
+ ConstructorDecl::getDelegatingOrChainedInitKind () const {
7754
+ return evaluateOrDefault (getASTContext ().evaluator ,
7755
+ BodyInitKindRequest{const_cast <ConstructorDecl *>(this )},
7756
+ BodyInitKindAndExpr ());
7756
7757
assert (hasBody () && " Constructor does not have a definition" );
7758
+ }
7757
7759
7758
- if (init)
7759
- *init = nullptr ;
7760
-
7761
- // If we already computed the result, return it.
7762
- if (Bits.ConstructorDecl .ComputedBodyInitKind ) {
7763
- auto Kind = static_cast <BodyInitKind>(
7764
- Bits.ConstructorDecl .ComputedBodyInitKind - 1 );
7765
- assert ((Kind == BodyInitKind::None || !init) &&
7766
- " can't return cached result with the init expr" );
7767
- return Kind;
7768
- }
7769
-
7770
-
7771
- struct FindReferenceToInitializer : ASTWalker {
7772
- const ConstructorDecl *Decl;
7773
- BodyInitKind Kind = BodyInitKind::None;
7774
- ApplyExpr *InitExpr = nullptr ;
7775
- DiagnosticEngine *Diags;
7776
-
7777
- FindReferenceToInitializer (const ConstructorDecl *decl,
7778
- DiagnosticEngine *diags)
7779
- : Decl(decl), Diags(diags) { }
7780
-
7781
- bool walkToDeclPre (class Decl *D) override {
7782
- // Don't walk into further nominal decls.
7783
- return !isa<NominalTypeDecl>(D);
7784
- }
7785
-
7786
- std::pair<bool , Expr*> walkToExprPre (Expr *E) override {
7787
- // Don't walk into closures.
7788
- if (isa<ClosureExpr>(E))
7789
- return { false , E };
7790
-
7791
- // Look for calls of a constructor on self or super.
7792
- auto apply = dyn_cast<ApplyExpr>(E);
7793
- if (!apply)
7794
- return { true , E };
7795
-
7796
- auto Callee = apply->getSemanticFn ();
7797
-
7798
- Expr *arg;
7799
-
7800
- if (isa<OtherConstructorDeclRefExpr>(Callee)) {
7801
- arg = apply->getArg ();
7802
- } else if (auto *CRE = dyn_cast<ConstructorRefCallExpr>(Callee)) {
7803
- arg = CRE->getArg ();
7804
- } else if (auto *dotExpr = dyn_cast<UnresolvedDotExpr>(Callee)) {
7805
- if (dotExpr->getName ().getBaseName () != DeclBaseName::createConstructor ())
7806
- return { true , E };
7807
-
7808
- arg = dotExpr->getBase ();
7809
- } else {
7810
- // Not a constructor call.
7811
- return { true , E };
7812
- }
7813
-
7814
- // Look for a base of 'self' or 'super'.
7815
- BodyInitKind myKind;
7816
- if (arg->isSuperExpr ())
7817
- myKind = BodyInitKind::Chained;
7818
- else if (arg->isSelfExprOf (Decl, /* sameBase*/ true ))
7819
- myKind = BodyInitKind::Delegating;
7820
- else {
7821
- // We're constructing something else.
7822
- return { true , E };
7823
- }
7824
-
7825
- if (Kind == BodyInitKind::None) {
7826
- Kind = myKind;
7827
-
7828
- // If we're not emitting diagnostics, we're done.
7829
- if (!Diags)
7830
- return { false , nullptr };
7831
-
7832
- InitExpr = apply;
7833
- return { true , E };
7834
- }
7835
-
7836
- assert (Diags && " Failed to abort traversal early" );
7837
-
7838
- // If the kind changed, complain.
7839
- if (Kind != myKind) {
7840
- // The kind changed. Complain.
7841
- Diags->diagnose (E->getLoc (), diag::init_delegates_and_chains);
7842
- Diags->diagnose (InitExpr->getLoc (), diag::init_delegation_or_chain,
7843
- Kind == BodyInitKind::Chained);
7844
- }
7845
-
7846
- return { true , E };
7847
- }
7848
- };
7849
-
7850
- FindReferenceToInitializer finder (this , diags);
7851
- getBody ()->walk (finder);
7852
-
7853
- // get the kind out of the finder.
7854
- auto Kind = finder.Kind ;
7855
-
7856
- auto *NTD = getDeclContext ()->getSelfNominalTypeDecl ();
7857
-
7858
- // Protocol extension and enum initializers are always delegating.
7859
- if (Kind == BodyInitKind::None) {
7860
- if (isa<ProtocolDecl>(NTD) || isa<EnumDecl>(NTD)) {
7861
- Kind = BodyInitKind::Delegating;
7862
- }
7863
- }
7864
-
7865
- // Struct initializers that cannot see the layout of the struct type are
7866
- // always delegating. This occurs if the struct type is not fixed layout,
7867
- // and the constructor is either inlinable or defined in another module.
7868
- if (Kind == BodyInitKind::None && isa<StructDecl>(NTD)) {
7869
- // Note: This is specifically not using isFormallyResilient. We relax this
7870
- // rule for structs in non-resilient modules so that they can have inlinable
7871
- // constructors, as long as those constructors don't reference private
7872
- // declarations.
7873
- if (NTD->isResilient () &&
7874
- getResilienceExpansion () == ResilienceExpansion::Minimal) {
7875
- Kind = BodyInitKind::Delegating;
7876
-
7877
- } else if (isa<ExtensionDecl>(getDeclContext ())) {
7878
- const ModuleDecl *containingModule = getParentModule ();
7879
- // Prior to Swift 5, cross-module initializers were permitted to be
7880
- // non-delegating. However, if the struct isn't fixed-layout, we have to
7881
- // be delegating because, well, we don't know the layout.
7882
- // A dynamic replacement is permitted to be non-delegating.
7883
- if (NTD->isResilient () ||
7884
- (containingModule->getASTContext ().isSwiftVersionAtLeast (5 ) &&
7885
- !getAttrs ().getAttribute <DynamicReplacementAttr>())) {
7886
- if (containingModule != NTD->getParentModule ())
7887
- Kind = BodyInitKind::Delegating;
7888
- }
7889
- }
7890
- }
7891
-
7892
- // If we didn't find any delegating or chained initializers, check whether
7893
- // the initializer was explicitly marked 'convenience'.
7894
- if (Kind == BodyInitKind::None && getAttrs ().hasAttribute <ConvenienceAttr>())
7895
- Kind = BodyInitKind::Delegating;
7896
-
7897
- // If we still don't know, check whether we have a class with a superclass: it
7898
- // gets an implicit chained initializer.
7899
- if (Kind == BodyInitKind::None) {
7900
- if (auto classDecl = getDeclContext ()->getSelfClassDecl ()) {
7901
- if (classDecl->hasSuperclass ())
7902
- Kind = BodyInitKind::ImplicitChained;
7903
- }
7904
- }
7905
-
7906
- // Cache the result if it is trustworthy.
7907
- if (diags) {
7908
- auto *mutableThis = const_cast <ConstructorDecl *>(this );
7909
- mutableThis->Bits .ConstructorDecl .ComputedBodyInitKind =
7910
- static_cast <unsigned >(Kind) + 1 ;
7911
- if (init)
7912
- *init = finder.InitExpr ;
7913
- }
7914
-
7915
- return Kind;
7760
+ void ConstructorDecl::clearCachedDelegatingOrChainedInitKind () {
7761
+ getASTContext ().evaluator .clearCachedOutput (
7762
+ BodyInitKindRequest{const_cast <ConstructorDecl *>(this )});
7916
7763
}
7917
7764
7918
7765
SourceRange DestructorDecl::getSourceRange () const {
0 commit comments