Skip to content

Support looser emitted version pragmas #1

Description

@charles-cooper

co-authored by OpenAI GPT-5.5

Problem

vyupgrade --target-version 0.5.0a2 --write currently rewrites source pragmas to an exact target pragma:

#pragma version 0.5.0a2

For migrated contracts, it would often be nicer to emit a looser accepted range, for example:

#pragma version >=0.5.0a2,<0.6.0

The tool already accepts a version spec as --target-version and validates against the resolved compiler version, so users can work around this today with:

vyupgrade --target-version '>=0.5.0a2,<0.6.0' --write contract.vy

But that behavior is not obvious, and it couples compiler target selection with the pragma text written to source.

Design options

1. Document the existing behavior

Document that --target-version accepts a version spec, not just an exact version.

Example:

vyupgrade --target-version '>=0.5.0a2,<0.6.0' --write contract.vy

Pros:

  • Minimal implementation.
  • Keeps current semantics.
  • Existing validation path remains unchanged.

Cons:

  • Still overloads --target-version as both compiler selection and emitted pragma text.
  • Users may expect --target-version 0.5.0a2 to produce a practical loose pragma.

2. Add an output-only pragma option

Add a separate flag for the pragma text to write:

vyupgrade --target-version 0.5.0a2 \
  --pragma-version '>=0.5.0a2,<0.6.0' \
  --write contract.vy

Semantics:

  • --target-version selects the target compiler and migration rule context.
  • --pragma-version controls only the source pragma emitted by VY001 and target validation overlays.

Pros:

  • Clean separation of compiler target vs source pragma policy.
  • Keeps exact compiler-backed validation explicit.
  • Backward compatible.

Cons:

  • Adds another CLI/config option.
  • Need to decide whether validation overlays use target compiler version or pragma output text.

3. Add a pragma policy option

Add a higher-level policy:

vyupgrade --target-version 0.5.0a2 --pragma-policy minor-range --write contract.vy

Possible policies:

exact       -> #pragma version 0.5.0a2
minor-range -> #pragma version >=0.5.0a2,<0.6.0
preserve    -> keep existing pragma if it admits the target; otherwise rewrite
none        -> do not rewrite/add version pragmas

Pros:

  • Easier common-case UX than manually writing specs.
  • Can preserve old behavior with exact as the default.
  • Gives clear user intent.

Cons:

  • More behavior to specify and test.
  • preserve requires careful version-spec satisfiability checks.

4. Change the default output to a compatible range

For exact target input, emit a range by default:

0.4.3   -> >=0.4.3,<0.5.0
0.5.0a2 -> >=0.5.0a2,<0.6.0

Pros:

  • Best default output for many users.
  • No extra flags.

Cons:

  • Breaking output change.
  • Some users may want exact, reproducible compiler pragmas.
  • Needs careful prerelease semantics.

5. Preserve-compatible rewrite only

If an existing pragma already admits the target version, leave it alone. Only rewrite when the target is excluded.

Examples:

#pragma version >=0.4.0,<0.6.0

Target 0.5.0a2: leave unchanged.

#pragma version >=0.4.0,<0.5.0

Target 0.5.0a2: rewrite to a compatible target range.

Pros:

  • Avoids unnecessary pragma churn.
  • Aligns with least-surprise migration behavior.

Cons:

  • Existing broad pragmas can still include source versions that no longer parse migrated syntax.
  • Needs a clear safety rule for when preserving is valid.

Tentative preference

A conservative implementation could combine options 2 and 3:

  • Keep --target-version as the exact compiler/migration target.
  • Add --pragma-version for explicit emitted text.
  • Add --pragma-policy exact|minor-range|preserve|none, defaulting to current exact behavior.

That keeps the validation path precise while giving users direct control over source pragma looseness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions