@@ -3704,8 +3704,12 @@ static Type getTupleConformanceTypeWitness(DeclContext *dc,
3704
3704
3705
3705
bool swift::
3706
3706
printRequirementStub (ValueDecl *Requirement, DeclContext *Adopter,
3707
- Type AdopterTy, SourceLoc TypeLoc, raw_ostream &OS) {
3708
- if (isa<ConstructorDecl>(Requirement)) {
3707
+ Type AdopterTy, SourceLoc TypeLoc, raw_ostream &OS,
3708
+ bool withExplicitObjCAttr) {
3709
+ // We sometimes use this for @implementation extensions too.
3710
+ bool forProtocol = isa<ProtocolDecl>(Requirement->getDeclContext ());
3711
+
3712
+ if (isa<ConstructorDecl>(Requirement) && forProtocol) {
3709
3713
if (auto CD = Adopter->getSelfClassDecl ()) {
3710
3714
if (!CD->isSemanticallyFinal () && isa<ExtensionDecl>(Adopter)) {
3711
3715
// In this case, user should mark class as 'final' or define
@@ -3731,15 +3735,35 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
3731
3735
ExtraIndentStreamPrinter Printer (OS, StubIndent);
3732
3736
Printer.printNewline ();
3733
3737
3738
+ PrintOptions Options = PrintOptions::printForDiagnostics (
3739
+ AccessLevel::Private, Ctx.TypeCheckerOpts .PrintFullConvention );
3740
+ Options.PrintDocumentationComments = false ;
3741
+ Options.PrintAccess = false ;
3742
+ Options.SkipAttributes = true ;
3743
+ Options.FunctionDefinitions = true ;
3744
+ Options.PrintAccessorBodiesInProtocols = true ;
3745
+ Options.PrintExplicitAccessorParameters = false ;
3746
+ Options.FullyQualifiedTypesIfAmbiguous = true ;
3747
+
3748
+ if (withExplicitObjCAttr) {
3749
+ if (auto runtimeName = Requirement->getObjCRuntimeName ()) {
3750
+ llvm::SmallString<32 > scratch;
3751
+ Printer.printAttrName (" @objc" );
3752
+ Printer << " (" << runtimeName->getString (scratch) << " )" ;
3753
+ Printer.printNewline ();
3754
+ Options.ExcludeAttrList .push_back (DeclAttrKind::ObjC);
3755
+ }
3756
+ }
3757
+
3734
3758
AccessLevel Access =
3735
3759
std::min (
3736
3760
/* Access of the context */
3737
3761
Adopter->getSelfNominalTypeDecl ()->getFormalAccess (),
3738
3762
/* Access of the protocol */
3739
- Requirement->getDeclContext ()->getSelfProtocolDecl ()->
3740
- getFormalAccess ());
3741
- if (Access == AccessLevel::Public )
3742
- Printer << " public " ;
3763
+ Requirement->getDeclContext ()->getSelfNominalTypeDecl ()
3764
+ -> getFormalAccess ());
3765
+ if (Access > AccessLevel::Internal )
3766
+ Printer. printKeyword ( getAccessLevelSpelling (Access), Options, " " ) ;
3743
3767
3744
3768
if (auto MissingTypeWitness = dyn_cast<AssociatedTypeDecl>(Requirement)) {
3745
3769
Printer << " typealias " << MissingTypeWitness->getName () << " = " ;
@@ -3753,7 +3777,7 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
3753
3777
3754
3778
Printer << " \n " ;
3755
3779
} else {
3756
- if (isa<ConstructorDecl>(Requirement)) {
3780
+ if (isa<ConstructorDecl>(Requirement) && forProtocol ) {
3757
3781
if (auto CD = Adopter->getSelfClassDecl ()) {
3758
3782
if (!CD->isFinal ()) {
3759
3783
Printer << " required " ;
@@ -3763,15 +3787,6 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
3763
3787
}
3764
3788
}
3765
3789
3766
- PrintOptions Options = PrintOptions::printForDiagnostics (
3767
- AccessLevel::Private, Ctx.TypeCheckerOpts .PrintFullConvention );
3768
- Options.PrintDocumentationComments = false ;
3769
- Options.PrintAccess = false ;
3770
- Options.SkipAttributes = true ;
3771
- Options.FunctionDefinitions = true ;
3772
- Options.PrintAccessorBodiesInProtocols = true ;
3773
- Options.FullyQualifiedTypesIfAmbiguous = true ;
3774
-
3775
3790
bool AdopterIsClass = Adopter->getSelfClassDecl () != nullptr ;
3776
3791
// Skip 'mutating' only inside classes: mutating methods usually
3777
3792
// don't have a sensible non-mutating implementation.
@@ -3797,9 +3812,12 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
3797
3812
};
3798
3813
Options.setBaseType (AdopterTy);
3799
3814
Options.CurrentModule = Adopter->getParentModule ();
3800
- if (isa<NominalTypeDecl>(Adopter)) {
3801
- // Create a variable declaration instead of a computed property in
3802
- // nominal types...
3815
+
3816
+ // Can the conforming declaration declare a stored property?
3817
+ auto ImplementedAdopter = Adopter->getImplementedObjCContext ();
3818
+ if (isa<NominalTypeDecl>(ImplementedAdopter) &&
3819
+ (!isa<EnumDecl>(ImplementedAdopter) || Requirement->isStatic ())) {
3820
+ // Create a variable declaration instead of a computed property...
3803
3821
Options.PrintPropertyAccessors = false ;
3804
3822
3805
3823
// ...but a non-mutating setter requirement will force us into a
@@ -3810,6 +3828,11 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
3810
3828
if (const auto Set = VD->getOpaqueAccessor (AccessorKind::Set))
3811
3829
if (Set->getAttrs ().hasAttribute <NonMutatingAttr>())
3812
3830
Options.PrintPropertyAccessors = true ;
3831
+
3832
+ // If we're not printing the accessors, make them affect the introducer
3833
+ // instead.
3834
+ Options.InferPropertyIntroducerFromAccessors =
3835
+ !Options.PrintPropertyAccessors ;
3813
3836
}
3814
3837
Requirement->print (Printer, Options);
3815
3838
Printer << " \n " ;
0 commit comments