Skip to content

[ParseableInterface] Standardize printing for accessors #20250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

harlanhaskins
Copy link
Contributor

@harlanhaskins harlanhaskins commented Nov 2, 2018

We want to make sure we are consistent when printing accessors.
@jrose-apple and I landed on the following table for disambiguating all
the possible combinations of accessors:

Computed Properties

Semantics Syntax
Read-only var x: T { get }
Read-write var x: T { get set }

Stored Properties

Semantics Syntax
Immutable let x: T
Mutable (trivial setter) var x: T
Mutable (custom setter) @_hasStorage var x: T { get set }
Private(set) @_hasStorage var x: T { get }

This patch introduces the @_hasStorage attribute which is printed for declarations that have storage and need to print custom accessors.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some IRGen tests to demonstrate that we're computing layout correctly in all cases?

@@ -838,6 +843,11 @@ static bool hasNonMutatingSetter(const AbstractStorageDecl *ASD) {
return setter && setter->isExplicitNonMutating();
}

static bool isSimpleStoredWithPublicSetter(const AbstractStorageDecl *asd) {
return asd->getImplInfo().isSimpleStored() &&
!asd->getAttrs().hasAttribute<SetterAccessAttr>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem right; it could be an open var with a public(set) (though I don't exactly know if we support that), or a public var with a @usableFromInline setter (though I don't know if we support that), or even a public var with a public(set) (which is only a warning).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could be an open var with a public(set)

We do currently support this, so I'm gonna check for non-public-or-usableFromInline in the AccessLevel

a public var with a @usableFromInline setter

Technically we support this on internal computed properties, but those won't get printed in interfaces at all.

or even a public var with a public(set)

😢

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check I'm doing now is if the setter's access level is less than the access level of the storage decl itself. Is that right?

@harlanhaskins
Copy link
Contributor Author

@jrose-apple For the IRGen tests, should I do it as a SIL test instead since this attribute doesn't exist outside of interfaces and interfaces don't reach IRGen?

@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from 260def1 to 7aca737 Compare November 3, 2018 01:32
@@ -4699,6 +4699,42 @@ static void diagnoseAndIgnoreObservers(Parser &P,
}
}

static StorageImplInfo classifyWithHasStorageAttr(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rjmccall This patch introduces a @_hasStorage attribute that allows us to break an ambiguity in parseable interfaces.

The mapping we've settled on is an understanding that

public private(set) var x: Int

maps to

@_hasStorage public var x: Int { get }

and

public var x: Int {
  willSet/didSet {}
}

maps to

@_hasStorage public var x: Int { get set }

With that in mind, is this mapping correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to rename the @_sil_stored attribute for this purpose.

If you're changing this, could you change it to list/expect all the public accessors, i.e. including modify and (eventually) _read? You might need to (1) move the logic for deciding the opaque accessors into Sema and then (2) change StorageImplInfo to store that bitset.

Copy link
Contributor Author

@harlanhaskins harlanhaskins Nov 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to handle _modify and _read if @_hasStorage is provided. Should they diagnose?

What are the semantics of @sil_stored var x: T { get set } vs. just @sil_stored var x: T? Or for @sil_stored let x: T { get } vs. just @sil_stored let x: T?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently it declares that the accessors are actually available. I'm not sure that's important to know in SIL. I do think there's a strong argument for it being useful to unambiguously list out the available opaque accessors, but it should be the full set, not just {get set} and then inferring modify and read and so on. However, to express that properly, you might have to change the representation a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to do this in a future patch, because testing parseable interfaces is currently blocked on this representational change. For now, there's a loud FIXME explaining how it should eventually work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

@jrose-apple
Copy link
Contributor

For the IRGen tests, should I do it as a SIL test instead since this attribute doesn't exist outside of interfaces and interfaces don't reach IRGen?

I was thinking that you'd IRGen a client that imports an interface.

@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from 7aca737 to 12c8673 Compare November 8, 2018 20:04
@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch 3 times, most recently from ac54aca to 5283507 Compare November 15, 2018 02:44
@harlanhaskins
Copy link
Contributor Author

@jrose-apple Does the IRGen test look good?

@@ -340,7 +340,7 @@ class C {

// CHECK-LABEL: @readIdentifiedClass
// CHECK: [read] Class %0 = argument of bb0 : $C
// CHECK: Field: @_hasStorage var property: Int
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are changed because this printer doesn't print for SIL. I could tell it to print for SIL, but that would cause other tests to print slightly differently, and this output isn't intended to convey full semantics.

@harlanhaskins
Copy link
Contributor Author

Addresses rdar://43815861

// RUN: %target-swift-frontend -emit-ir %s -I %t -enable-parseable-module-interface | %FileCheck %s -check-prefix CHECK -check-prefix COMMON

// RUN: %target-swift-frontend -typecheck %S/stored-properties.swift -enable-resilience -module-name StoredProperties -emit-parseable-module-interface-path %t/StoredProperties.swiftinterface
// RUN: %target-swift-frontend -emit-ir %s -I %t -enable-parseable-module-interface | %FileCheck %s -check-prefix RESILIENT -implicit-check-not CHECK -check-prefix COMMON
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-implicit-check-not adds a negative pattern, not a negative prefix. What do you actually want to check here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to make sure the // CHECK lines ensure those lines don't appear in the resilient check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a way to do that today, but I think it's okay for this test.

@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from 0a60559 to 3efd393 Compare November 15, 2018 21:30
@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 3453bf5fc0d0a4fce0eb8ce934e7dd8a46a4adbd

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 3453bf5fc0d0a4fce0eb8ce934e7dd8a46a4adbd

@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from 3efd393 to 893b07c Compare November 16, 2018 01:00
@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 3efd393ae2041ceb4f2080417ebe8fde7b6448bc

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 3efd393ae2041ceb4f2080417ebe8fde7b6448bc

@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 893b07c9082749c9fe189d3a0a062b608fbe4e61

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 893b07c9082749c9fe189d3a0a062b608fbe4e61

@@ -12,7 +12,7 @@ import StoredProperties
/// layout and use the right access patterns in the presence of a
/// .swiftinterface file, in both resilient and non-resilient cases.

// COMMON: %[[BAGOFVARIABLES:T16StoredProperties14BagOfVariablesV]] = type <{ %TSi, %TSb, [7 x i8], %TSi }>
// COMMON: %[[BAGOFVARIABLES:T16StoredProperties14BagOfVariablesV]] = type <{ %TSi, %TSb, [{{[0-9]}} x i8], %TSi }>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the thing we're supposed to be checking, though…can you do it as {{7|9}} or something like that? Or use FileCheck's fancy new -D feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd want it to be {{3|7}}, because it's going to pad to word boundaries after a Bool.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just made up numbers, go for it.

@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from 5a501fc to f5eb9a5 Compare November 26, 2018 22:21
@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 5a501fc277ed91fe4089396756c7a502619539ff

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 5a501fc277ed91fe4089396756c7a502619539ff

Harlan Haskins added 8 commits November 26, 2018 18:40
We want to make sure we are consistent when printing accessors.
@jrose-apple and I landed on the following table for disambiguating all
the possible combinations of accessors:

\### Computed Properties

| Semantics  | Syntax                 |
|------------|------------------------|
| Read-only  | var x: T { get }       |
| Read-write | var x: T { get set }   |

\### Stored Properties

| Semantics                | Syntax                              |
|--------------------------|-------------------------------------|
| Immutable                | let x: T                            |
| Mutable (trivial setter) | var x: T                            |
| Mutable (custom setter)  | @_hasStorage var x: T { get set }   |
| Private(set)             | @_hasStorage var x: T { get }       |

This first commit enables printing @_hasStorage outside of SIL mode.
@harlanhaskins harlanhaskins force-pushed the accessory-to-a-git-crime branch from f5eb9a5 to ac249e6 Compare November 27, 2018 02:42
@harlanhaskins
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - f5eb9a5e5d75db1d579ed32afad80c41c205cd6c

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - f5eb9a5e5d75db1d579ed32afad80c41c205cd6c

@harlanhaskins harlanhaskins merged commit 245109d into swiftlang:master Nov 27, 2018
@harlanhaskins harlanhaskins deleted the accessory-to-a-git-crime branch November 27, 2018 18:31
jrose-apple pushed a commit to jrose-apple/swift that referenced this pull request Dec 12, 2018
 [ParseableInterface] Standardize printing for accessors

(cherry picked from commit 245109d)
if (*setterAccess < *accessLevel) {
AddAttribute(
new (ctx) SetterAccessAttr(SourceLoc(), SourceLoc(),
*setterAccess, /*implicit*/true));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unfortunate. I wish I had noticed it at the time, but it's weird to be different from the regular access.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's unfortunate, but I'm not sure how else to preserve this. The rest of the compiler assumes setter access is determined by the presence of this attribute. If there's a better way than synthesizing this here, I'm happy to change it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants