SE-0254: Static and class subscripts

The review of SE-0254: Static and class subscripts begins now and runs through Tuesday, April 9th, 2019. Toolchains are available for macOS and Ubuntu Linux 16.04 to try out this feature.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager via email or direct message on the forums. If you send me email, please put "SE-0254" somewhere in the subject line.

What goes into a review of a proposal?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When reviewing a proposal, here are some questions to consider:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thank you for contributing to Swift!

Doug Gregor
Review Manager

20 Likes

+1. I've been following the pitch for this and I really like the syntax and design. Overall this proposal seems like it makes the language more consistent and predictable, in a thoughtful way. I'm a bit sad to see metatype key paths pushed forward, but the reasoning makes sense. Let's get static subscripts right first. Thanks, Doug and Brent!

1 Like

Like other discrepancies between functions and subscripts (most of which are already fixed these days :), I see this practically as a bug fix rather than a language change, so I'm very much in favor of this proposal.

8 Likes

+1. Looking forward to seeing static callable go in this direction as well in the future. I work with metatypes on a regular basis and would like to see as many limitations on them lifted as possible.

2 Likes

+1 for these reasons, along with whatever I said last time they came up :-)

+1

A completely obvious fix to improve the consistency of the language.

+1. Useful, obvious and straightforward syntax, makes the language more consistent, doesn't seem like it would break anything.

+2

1 Like

+1 from me.

Hi @Douglas_Gregor – I'd vote for keeping the syntax in reserve for three reasons:

  1. If by accident or by design the language ever backs itself into a corner with the generics "angle brackets" syntax, then switching to square brackets is a reasonable backup plan (i.e. Optional[String] instead of Optional<String>).
  2. If we ever wanted to have allocator parameters, then using square brackets could be nice (but certainly not the only way). For example: let someClass = SomeClass[allocParam]<SomeType>().
  3. If we ever wanted to have something like llvm::TrailingObjects, then again, the square bracket syntax could be useful (and also not the only way).

Unless I'm misunderstanding you, 1. seems extremely implausible, and the other two reasons cover features that seem like they would be rarely used (or never implemented in the language at all), so it's hard for me to imagine using this syntax in an inconsistent way for them.

The proposal looks good.

A comment on the eventual SourceKit interface: currently we have separate kinds for instance/static properties and functions (source.lang.swift.decl.var.instance vs. source.lang.swift.decl.var.static and source.lang.swift.decl.function.method.instance vs. source.lang.swift.decl.function.method.static). I'd like to see the same kind of distinction for class and object subscript declarations to help tooling distinguish between the two types. They currently both come out as source.lang.swift.decl.function.subscript which I guess should remain as the instance version for compatibility.

I also noticed in the provided toolchain that the 'static' part is not round-tripping properly yet, easiest to see in swiftc -print-ast (or Xcode quick help).

1 Like
  • What is your evaluation of the proposal?
    +1 - I needed this feature in my code base too many times.

  • Is the problem being addressed significant enough to warrant a change to Swift?
    Yes.

  • Does this proposal fit well with the feel and direction of Swift?
    Yes.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    Read the proposal and the pitch thread.

1 Like

Given that even those of us in favor haven't been able to name too many use cases, I'd be interested in hearing about yours!

2 Likes

Thanks for the report—I'll take a look at that.

Here is one example: I have an API that uses key-paths to extract instances of a predefined endpoint types (bundle type with static information about bluetooth characteristics for custom peripherals we develop). These endpoints should be all static and lazy, but currently they aren't as key-paths cannot traverse static type members or static subscripts yet. One of these endpoints is computed by a subscript on some intermediate path. Even if there was no key-path limitation, this would be the next issue to overcome as all endpoints should be static. The current workaround requires me to create a single instance of those types that provide such endpoints, but that is not ideal as all of the endpoints are initialized right away with all their default values, which can be avoided with static laziness.

2 Likes

I don't find the single use case in the proposal to be very convincing. Perhaps I'm just too accustomed to how Cocoa does things, but it seems wrong to me that the metatype for Environment would be vending the environment instead of an instance. I think it should be something like Environment.common["PATH"], even if there can only be one instance (singleton).

I'm not really opposed to this change, but I'm not too thrilled either as I'm not too sure allowing metatypes to behave as collections should be encouraged.

  1. That would be extremely source-breaking.
  2. This proposal wouldn’t prevent that — you’d just have to implement it as a static generic subscript that returns a () -> Whatever, and which the trailing () at the callsite then executes.
  3. I don’t know enough about this one to comment.

I asked something similar in the pitch thread already. Here is the response:

I too am struggling to find a use case that isn't better solved some other way. The process environmental variables example from the proposal arguably should be modeled 1:1 with how the OS thinks about processes, and therefore the environmental variables would be a static var on a Process type.