@@ -3704,8 +3704,12 @@ static Type getTupleConformanceTypeWitness(DeclContext *dc,
37043704
37053705bool swift::
37063706printRequirementStub (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) {
37093713 if (auto CD = Adopter->getSelfClassDecl ()) {
37103714 if (!CD->isSemanticallyFinal () && isa<ExtensionDecl>(Adopter)) {
37113715 // In this case, user should mark class as 'final' or define
@@ -3731,15 +3735,35 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
37313735 ExtraIndentStreamPrinter Printer (OS, StubIndent);
37323736 Printer.printNewline ();
37333737
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+
37343758 AccessLevel Access =
37353759 std::min (
37363760 /* Access of the context */
37373761 Adopter->getSelfNominalTypeDecl ()->getFormalAccess (),
37383762 /* 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, " " ) ;
37433767
37443768 if (auto MissingTypeWitness = dyn_cast<AssociatedTypeDecl>(Requirement)) {
37453769 Printer << " typealias " << MissingTypeWitness->getName () << " = " ;
@@ -3753,7 +3777,7 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
37533777
37543778 Printer << " \n " ;
37553779 } else {
3756- if (isa<ConstructorDecl>(Requirement)) {
3780+ if (isa<ConstructorDecl>(Requirement) && forProtocol ) {
37573781 if (auto CD = Adopter->getSelfClassDecl ()) {
37583782 if (!CD->isFinal ()) {
37593783 Printer << " required " ;
@@ -3763,15 +3787,6 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
37633787 }
37643788 }
37653789
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-
37753790 bool AdopterIsClass = Adopter->getSelfClassDecl () != nullptr ;
37763791 // Skip 'mutating' only inside classes: mutating methods usually
37773792 // don't have a sensible non-mutating implementation.
@@ -3797,9 +3812,12 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
37973812 };
37983813 Options.setBaseType (AdopterTy);
37993814 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...
38033821 Options.PrintPropertyAccessors = false ;
38043822
38053823 // ...but a non-mutating setter requirement will force us into a
@@ -3810,6 +3828,11 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter,
38103828 if (const auto Set = VD->getOpaqueAccessor (AccessorKind::Set))
38113829 if (Set->getAttrs ().hasAttribute <NonMutatingAttr>())
38123830 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 ;
38133836 }
38143837 Requirement->print (Printer, Options);
38153838 Printer << " \n " ;
0 commit comments