Releases: xphp-lang/xphp
Release list
v0.2.1
What's Changed
Two high-impact defects are fixed:
- the CLI now runs correctly when xphp is installed as a Composer dependency
- 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/implementsa 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 innew/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
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 barenew Cache;for all-defaults templates. - Variance —
+T/-Tmarkers with parse-time position checks and
real subtype edges:Producer<Banana>actually extends
Producer<Fruit>whenBanana extends Fruit. - Function-level generics — generic methods on static/instance
receivers, generic free functions, and nullsafe turbofish
$obj?->m::<T>(). - Generic closures & arrows —
function<T>(…){…}andfn<T>(…) => …,
includinguse (…)and by-refuse (&$x)captures. - Pseudo-types —
self<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::<...>.
Parenlessnew 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, andstaticclosures, 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/xphpFull changelog: v0.1.0...v0.2.0
v0.1.0
Merge pull request #13 from xphp-lang/split-repos repo: collapse monorepo to single xphp package