-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[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
[ParseableInterface] Standardize printing for accessors #20250
Conversation
There was a problem hiding this 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?
lib/AST/ASTPrinter.cpp
Outdated
@@ -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>(); |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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 apublic(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 apublic(set)
😢
There was a problem hiding this comment.
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?
@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? |
260def1
to
7aca737
Compare
@@ -4699,6 +4699,42 @@ static void diagnoseAndIgnoreObservers(Parser &P, | |||
} | |||
} | |||
|
|||
static StorageImplInfo classifyWithHasStorageAttr( |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
I was thinking that you'd IRGen a client that imports an interface. |
7aca737
to
12c8673
Compare
ac54aca
to
5283507
Compare
@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 |
There was a problem hiding this comment.
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.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
@swift-ci please test |
0a60559
to
3efd393
Compare
@swift-ci please test |
Build failed |
Build failed |
3efd393
to
893b07c
Compare
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please test |
Build failed |
Build failed |
@@ -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 }> |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
5a501fc
to
f5eb9a5
Compare
@swift-ci please test |
Build failed |
Build failed |
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.
f5eb9a5
to
ac249e6
Compare
@swift-ci please test |
Build failed |
Build failed |
[ParseableInterface] Standardize printing for accessors (cherry picked from commit 245109d)
if (*setterAccess < *accessLevel) { | ||
AddAttribute( | ||
new (ctx) SetterAccessAttr(SourceLoc(), SourceLoc(), | ||
*setterAccess, /*implicit*/true)); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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
var x: T { get }
var x: T { get set }
Stored Properties
let x: T
var x: T
@_hasStorage var x: T { get 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.