I like the general idea and prefer:
@exposed(inlinable)
@exposed(linkable)
And perhaps in the future for constants:
@exposed(value)
I don't think we should drop the parentheses, but I don't know how that will affect using it with @available
.
I like the general idea and prefer:
@exposed(inlinable)
@exposed(linkable)
And perhaps in the future for constants:
@exposed(value)
I don't think we should drop the parentheses, but I don't know how that will affect using it with @available
.
What about emphasizing this with the naming?
@compiler(inlinable, abiPublic)
If you want to group these attributes in an extensible way like this then I'm not sure @compiler
is the best spelling, because every attribute is a directive to the compiler so it's hard to decide which attributes should be in that group. I think it might be better with a more explicit name, (e.g. @crossModule
, @resilience
, @abi
, @exported
, whatever), which would make it more obvious whether an attribute belongs in the group or not, and perhaps makes it possible to use shorter names within the group.
I've kind of lost track of exactly the status of this discussion is, though. I guess there are a lot of difference naming options, and I don't see much consensus over whether a single attribute or some sort of grouping structure is preferred.
I like this suggestion; I don't think I've seen it before, but it seems like a very succinct way of describing (at least in general terms) what's going on.
I like @resilience as well.
The concept of resilience encompasses much more than these two attributes. Using @resilience
here would introduce a narrower meaning (limited to @resilience(inlinable)
and @resilience(linkable)
) and make it harder to discuss or comprehend the broader concept of resilience because the two concepts would have the same name.
Beside, we already have a general attribute for controlling promises made for resilience purposes: @available
.
And that thought sorts of brings us back at the starting point... we could just use:
@available(*, inlinable)
@available(*, linkable)
Haha.
Yeah I'm moving towards @available
.
Looking at the LibraryEvolution documentation (swift/LibraryEvolution.rst at main · apple/swift · GitHub), I think it's a good fit. It seems like many (all?) uses of @inlineable
or @abiPublic
will be accompanied by an @available
anyway.
@available(1.2)
public func summonDemons()
@available(1.0)
@available(1.2, inlineable)
public func summonElves()
It's a flexible, parameterised attribute which can easily expand to other kinds of binary guarantees.
My thoughts on the current @available
syntax are well known, so I won't repeat them here.
I very much like the formulation mentioned above that "resilience" is about answering the question, "what things can or can't I change in the future?". For me, @available
is predominantly an answer to the question, "what things have already changed in the past?". I think those two are distinguishable attributes, if we want them to be.
I appreciate everyone's thoughtful comments since this review was kicked back for a second round 17 days ago. When considering the review discussion, I want to first highlight something I said when the second review was initiated:
Using syntax like @available
was definitely something that was proposed — and is still a candidate design — for a broader design for articulating library evolution concepts. That design, however, is pending once we have a complete API versioning scheme in place.
Where this review went is that it was recognized that in the absence of having a full versioning scheme that these attributes would be immediately useful. Thus the intention of this second review was to have some narrowly focused attributes that — in the fullness of time — either possibly served as syntactic sugar for specific cases in a broader library evolution attribute design or were syntax that would one day be deprecated.
If the consensus on this thread is to hold off having dedicated (and narrowly focused) attributes until a broader versioning scheme is in place (i.e., when we have the option to tie in with attributes such as @available
) that is definitely an option. However, that means expressing these concepts will remain something that only the Standard Library can do until that comes along. On the other hand, if the feeling is that there is real use in having these attributes available today, then I think we should consider some narrowly focused names.
My preference — as a participant on this thread and not the review manager — is to keep with simple spellings like @inlinable
and @usableFromInline
(an alternate spelling for @usableFromInlinable
suggested to me by @dabrahams). We can then leverage the thoughts on this review concerning @resilience
, @available
, etc., as part of a broader library evolution design.
I'm happy with @inlinable
and @usableFromInline
to enable libraries to take advantage of these features today, and I think they are valuable enough that they shouldn't wait for a grand redesign of resilience attributes. As you say, if/when such a design appears, these can be treated as redundant aliases and possibly eventually deprecated. I've heard people say several times in the history of the mailing list/forums that they have had to copy library code into their project to get acceptable performance, which is clearly suboptimal.
One recurrent theme in the discussion has been about clarifying that "inlinable" only affects how other libraries access a function -- that it has no effect internally in the module -- and writing it as either @exposure(inlinable)
, @resilience(inlinable)
or @available(*, inlinable)
narrows the context enough to clarify that this is about access by other libraries. The fact that expressing the attribute this way provides what looks like a nice hook for a broader resilience system is an unfortunate accident.
It'd be disappointing if that would cause the feature to be delayed. Except the feature is already there through @_inlineable
and @_versioned
, so what we'd end up delaying is just the final syntax, not the feature itself. Maybe it's worth the wait.
One clarifying point I should make is that the feature does not exist today except for the Standard Library. Underscored attributes have absolutely no promise of source compatibility whatsoever. They are intended to be internal hooks for the Standard Library that can (one day) be generalized for broader use. If we accept syntax like @inlinable
, we are committing to enough of a source compatibility story that non-Standard Library clients can use it.
I thought the conclusion from the frozen enum debate was that resilience attributes basically only affect Apple right now, so it's okay to have a semi-private (SPI) solution while we wait a more comprehensive versioning strategy.
In that case, I'd rather keep the underscore for the time being.
I think there is value in making incremental progress here on the library evolution story where possible. SE-0192 has its own set of concerns which are related but different to this proposal. Right now there is value in exposing @inlinable
as a tool some library authors can use, particularly those vending packages via SwiftPM, because of optimization barriers in place because of the current capabilities of the tools. Further, since we know the desired semantics of @inlinable
there is value in releasing it now for people to use. Lastly, many projects won't care about versioning when using @inlinable
, but versioning is inevitably tied up in the design if pulling this functionality into syntax such as @available
.
With SE-0192 the main reason to make the frozen versus non-frozen changes apply to the Standard Library and overlays only is because there is little value to do otherwise for the general Swift ecosystem at this point in time. That's not the case here — which I think is a stark difference in how these two proposals should be evaluated.
Fair point, nothing to add
To be clear, I very much respect your perspective here. I just wanted to make sure we didn't overly collapse the distinct concerns of these two proposals together when weighing what to do here.
The Core Team decided to accept this proposal with the respective spellings of @inlinable
and @usableFromInline
. The final proposal version will be amended with these changes.
When discussing the review thread with the Core Team, @Slava_Pestov (proposal author) also brought up the following question:
Should @inlinable imply @usableFromInline for internal declarations? Otherwise, you always need both attributes if the decl is internal.
While this was not brought up on the review thread, this seems like a natural extension to the proposal and the Core Team is OK with including that as part of the final revision without extending the review.
There was some incredibly insightful feedback on this review thread. Similar to discussions on this proposal that happened between various members of the Core Team and @Slava_Pestov, the discussion touched on syntax that bespoke to a broader language feature for supporting concepts for library evolution. That feedback will provide useful insights when designing those concepts more comprehensively. In the meantime, the Core Team felt that adding @inlinable
and @usableFromInline
would help address some immediate concerns for library authors and could naturally be folded into a larger library evolution design.
Thank you to everyone who participated in this review. The discussion was fantastic!
Ted Kremenek
Review Manager