Skip to content

Releases: xphp-lang/xphp

v0.2.1

Choose a tag to compare

@math3usmartins math3usmartins released this 17 Jun 19:05
b39788e

What's Changed

Two high-impact defects are fixed:

  1. the CLI now runs correctly when xphp is installed as a Composer dependency
  2. specialized generics no longer break at autoload when they reference imported built-in classes or
    interfaces.

The rest of the release hardens test coverage and documentation for behavior that already shipped in 0.2.0.

No language or API changes; upgrading is drop-in.

Bug fixes

CLI runs when installed as a dependency

vendor/bin/xphp failed at startup for every project that installed xphp as a
(dev) dependency:

Fatal error: Failed opening required '.../vendor/xphp-lang/xphp/vendor/autoload.php'

The entrypoint hardcoded a path to its own vendor/autoload.php, which only
exists in a standalone checkout. It now locates Composer's autoloader across all
install layouts — the bin-proxy path, the consuming project's
vendor/autoload.php, and a standalone checkout (the path the bundled PHAR also
uses) — and prints a clear, non-fatal message if none can be found.

Impact: the documented workflow (vendor/bin/xphp compile …, build scripts, CI)
now works for downstream consumers, not just inside this repository.

Specialized generics keep imported class/interface references valid

When a generic was specialized, its declaration was lifted into a generated
namespace, but bare class/interface names that relied on the source file's use
imports were copied verbatim. They then resolved into the generated namespace and
threw at load time:

Fatal error: Interface "XPHP\Generated\…\Countable" not found

This affected any template that, via an imported (unqualified) name:

  • extends / implements a built-in interface (Countable, IteratorAggregate,
    Traversable, ArrayAccess, …),
  • instantiates an imported class (new ArrayIterator(…)),
  • catches an imported exception (catch (SomeException $e)),
  • or references one in a property, parameter, return, union/nullable, or
    constant type hint.

The compiler now fully-qualifies every such non-generic reference when it emits a
specialized class, so the generated code is import-independent and loads cleanly.
Failures were silent at compile time and only surfaced on first autoload.

Upgrade note: the previous workaround — writing global/built-in names
fully-qualified with a leading \ in .xphp sources — is no longer required.
Existing fully-qualified names keep working unchanged.

Testing & tooling

  • Added a dedicated PHP 8.5 test runtime (container + CI group) and coverage for
    the PHP 8.5 pipe operator (|>) passing through the transpiler untouched.
  • Added end-to-end regression coverage for catching exceptions by generic
    specialization.
  • Added regression coverage for the two fixes above: a CLI bootstrap test that
    drives the binary in standalone, installed-as-dependency, and missing-autoloader
    layouts; and a fixture exercising generics that extend/implement built-ins and
    use imported classes in new / catch / type-hint positions.

Documentation

  • Documented catching exceptions via generic specialization and PHP 8.5
    syntax pass-through.
  • Fixed a broken README example and an incorrect cache-path reference.
  • Expanded the caveats guide and tidied the roadmap.

Full Changelog: v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@math3usmartins math3usmartins released this 12 Jun 10:19
85ff090

v0.1.0 specialized generic classes. v0.2.0 extends generics across the
whole declaration surface — classes, interfaces, traits, methods, free
functions, closures, and arrows — each with bounds, defaults, and
variance, behind forward-compatible turbofish syntax at every call site.

Still the same promise: it all compiles down to vanilla PHP with native
type hints and zero runtime dispatch.

Highlights

  • Type bounds, checked at compile time — single (<T: \Stringable>),
    intersection (T: \Stringable & \Countable), DNF
    ((\Stringable & \Countable) | \Iterator), and F-bounded
    (<T: Comparable<T>>). Errors point at your instantiation, not the
    generated hash.
  • Default type parameters everywhere — class, method, function,
    closure, arrow — with forward refs (Pair<A, B = A>), empty turbofish
    ::<>, and bare new Cache; for all-defaults templates.
  • Variance+T / -T markers with parse-time position checks and
    real subtype edges: Producer<Banana> actually extends
    Producer<Fruit> when Banana extends Fruit.
  • Function-level generics — generic methods on static/instance
    receivers, generic free functions, and nullsafe turbofish
    $obj?->m::<T>().
  • Generic closures & arrowsfunction<T>(…){…} and fn<T>(…) => …,
    including use (…) and by-ref use (&$x) captures.
  • Pseudo-typesself<T> / static<T> / parent<T> in type-hint
    and constructor positions.
  • Full docs/ tree — a per-feature syntax tour,
    getting started, how-it-works, runtime semantics, a type-system
    comparison, caveats, and errors.

Changed

  • Call-site syntax aligned with the PHP RFC: turbofish Name::<...>.
    Parenless new Name<...> is now rejected with a message pointing you at
    the ::<...> form.

Known limitations

See caveats for the full list. In short:

  • Variance markers are class-level only (not yet on methods, functions,
    closures, or arrows).
  • Generic closures/arrows that capture $this, and static closures, are
    rejected at the call site.
  • Reflection sees the dispatcher shape, not the original closure body.
  • The variance validator doesn't walk into trait-imported signatures.

Install

composer require xphp-lang/xphp

Full changelog: v0.1.0...v0.2.0

v0.1.0

Choose a tag to compare

@math3usmartins math3usmartins released this 01 Jun 20:30
cd45ad0
Merge pull request #13 from xphp-lang/split-repos

repo: collapse monorepo to single xphp package