Skip to content

Clarify usage patterns for feature gates #382

Closed
@vados-cosmonic

Description

@vados-cosmonic

Hey all, after some discussion in the following PRs:

bytecodealliance/wasm-tools#1689
bytecodealliance/jco#459

It seems like now would be a good time to discuss and really pin down the expected usage pattern of feature gates.

Intuitions seem to clash on how the gates should be used, so the decision should likely be discussed and made (hopefully quickly, if possible!) with a record for people to see the whys.

Context

At present, the WIT design feature gates section describes a reality that requires/implies a few things:

1. Package versions may not be present
There is no mention that a package containing @since() that is not itself versioned is a bug.

There are currently some tests in wasm-tools that use @since in packages that have no version specified (i.e. this is expected to be "right" or at least legal).

2. @since(version = v, feature = f) works as an OR

Then, once the feature is stable (and, in a WASI context, voted upon), the @unstable gate is switched to a @SInCE gate. To enable a smooth transition (during which producer toolchains are targeting a version earlier than the @since-specified version), the @SInCE gate contains an optional feature field that, when present, says to enable the feature when either the target version is greator-or-equal or the feature name is explicitly enabled by the developer.

This necessarily means that version is used or the feature is used.

**3. @since() may specify versions in the future

Thus, c is enabled if the version is 0.2.2 or newer or the fancy-foo feature is explicitly enabled by the developer.

The first part of this "if" can only work if you were able to specify a future (unreleased) version. It doesn't make sense to describe it like this unless a situation like this is possible:

// there's obviously quite a gap in these versions but hopefully it's useful for the sake of discussion.
package some:pkg@0.1.0;

@since(version = 0.2.2, feature = access-early-a)
interface a { ... }

Options for moving forward

There seem to be at least these three ways of handling it:

1. OR (current)
In this situation, we keep the functionality as it exists now. This requires the caveats mentioned above.

One of the questions associated with this approach is whether it makes sense for a package at version 0.1.0 to be able to have a @since(version = 0.2.0) in it at all.

2. AND (new)

In this situation version and feature are always both considered for enabling an item.

This has a few benefits I can think of:

  • Always knowing an import requires all the @since related options makes it easy to do things like infer requirements from an import (versus not knowing if that means you need a version or a feature)
  • It's possible to write features that actually change across versions, and versions that act differently w/ certain features enabled

3. Strict @unstable -> @since with ignored features after stabilization

Alex has laid out his intuition for this, which makes also makes sense.

Strictly moving from @unstable to @since and then ignoring features once enabled, along with making sure that future unreleased versions cannot be used in @since removes a lot of ambiguity.

What needs to be clarified

It would be nice if we could lay out the actual intended evolution of a feature through gates -- this is kind of already spelled out already in the WIT design doc, but there seems to be two levels of progression here:

  • unstable -> stable (experimental features)
  • not enabled version -> enabled version (future feature prep)

I think we're done at the point when we have:

  • A flow (probably best written out by steps) that people agree with that most importantly seems intuitive for users to follow (@unstable -> @since, @since(version = v) -> @since(version = v + 1) ?)
  • Which levels of progression the feature gates feature should be handling

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions