library #lib;
import self as self;
import "dart:core" as core;

class T1 extends core::Object {
  synthetic constructor •() → self::T1
    : super core::Object::•()
    ;
}
class T2 extends core::Object {
  synthetic constructor •() → self::T2
    : super core::Object::•()
    ;
}
abstract class A extends core::Object {
  synthetic constructor •() → self::A
    : super core::Object::•()
    ;
  abstract method foo() → dynamic;
}
class B extends self::A {
  synthetic constructor •() → self::B
    : super self::A::•()
    ;
[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method foo() → dynamic
    return new self::T1::•();
}
abstract class C extends core::Object implements self::B {
}
abstract class D extends core::Object {
  synthetic constructor •() → self::D
    : super core::Object::•()
    ;
}
abstract class _E&D&C extends self::D implements self::C {
  synthetic constructor •() → self::_E&D&C
    : super self::D::•()
    ;
}
class E extends self::_E&D&C {
  synthetic constructor •() → self::E
    : super self::_E&D&C::•()
    ;
[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method foo() → dynamic
    return new self::T2::•();
}
class Intermediate extends core::Object {
  synthetic constructor •() → self::Intermediate
    : super core::Object::•()
    ;
[@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false]  method bar(self::A aa) → dynamic
    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}();
}
[@vm.inferred-type.metadata=dart.core::Null?]static field core::Function unknown;
static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
  return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa);
static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
  return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa);
static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
  return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
  return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateB() → dynamic {
  new self::B::•();
}
static method allocateE() → dynamic {
  new self::E::•();
}
static method main(core::List<core::String> args) → dynamic {
  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
  self::allocateB();
  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
  self::allocateE();
  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
}
