xp-framework / compiler

Compiles future PHP to today's PHP.
19 stars 0 forks source link

Undefined constant Sources::FromEmpty #122

Closed thekid closed 3 years ago

thekid commented 3 years ago

Declaration (shortened for brevitiy):

<?php namespace org\example\imports;

use lang\Reflection;

enum Sources: string {
  case FromEmpty  = '__EMPTY__';
  case FromCampus = 'CAMPUS';

  /** Returns source kind */
  public function kind(): string { return $this->value; }

  /** Creates a new source instance with given arguments */
  public function newInstance(mixed... $args): Source {
    return Reflection::of(__NAMESPACE__)->type($this->name)->newInstance(...$args);
  }
}

Usage:

<?php namespace org\example\imports\unittest;

use org\example\imports\{Source, Sources};
use unittest\{Assert, Test};

class SourcesTest {

  #[Test]
  public function create_instance() {
    Assert::instance(Source::class, Sources::FromEmpty->newInstance());
  }
}

When compiling the unittest, Sources::FromEmpty is not detected as an enum constant!

thekid commented 3 years ago

This is because, for some reason, the Type class and its implementations' static initializers are run too late:

  1. Class loading for a non-compiled class is requested
  2. The compiling class loader starts up
  3. Its dependencies, including lang.ast.emit.Type, are loaded
  4. The class loader returns, but we're still in a class loading process, so static initializers are deferred
  5. Compilation finishes, a type is created
  6. The static initializers run - *this is too late, step 5 would need the information