resolveDeferredTypeParameterBounds method

void resolveDeferredTypeParameterBounds(
  1. STypeParameterList? typeParameters,
  2. Environment enclosing
)

SCE130: resolve any bound pass 1 had to leave unresolved.

A class's type-parameter bounds are resolved once, when pass 1 creates the placeholder, and nothing ever re-extracts them — so typedef N = num; class Box<T extends N> had to resolve N before any alias existed, and threw. A function does not need this because pass 2 REBUILDS it from its declaration; a class is populated in place, so the repair has to be explicit and this is it.

Called from pass 2's visitClassDeclaration, after imports and the type alias fixpoint. A bound that still does not resolve throws HERE, which is what keeps a genuinely undefined bound reportable.

Implementation

void resolveDeferredTypeParameterBounds(
  STypeParameterList? typeParameters,
  Environment enclosing,
) {
  if (typeParameters == null) return;
  Environment? scope;
  for (final typeParam in typeParameters.typeParameters) {
    final boundNode = typeParam.bound;
    if (boundNode == null) continue;
    final paramName = typeParam.name?.name ?? '';
    if (typeParameterBounds[paramName] != null) continue;
    // The class's own parameters must be visible to a bound that names one
    // (`class P<A, B extends A>`), exactly as in pass 1.
    if (scope == null) {
      scope = Environment(enclosing: enclosing);
      for (final p in typeParameters.typeParameters) {
        final n = p.name?.name ?? '';
        scope.define(n, TypeParameter(n));
      }
    }
    typeParameterBounds[paramName] = resolveTypeAnnotationDynamic(
      boundNode,
      scope,
    );
  }
}