library;
import self as self;
import "dart:core" as core;
import "forwarder_propagation_lib.dart" as for;

import "org-dartlang-testcase:///forwarder_propagation_lib.dart";

abstract class A extends core::Object {
  synthetic constructor •() → self::A
    : super core::Object::•()
    ;
  abstract set foo(core::int value) → void;
  abstract get bar() → core::int;
  abstract method baz(core::int x, {core::String y = #C1, core::double z = #C1}) → void;
}
class B extends core::Object implements self::A {
  synthetic constructor •() → self::B
    : super core::Object::•()
    ;
  method noSuchMethod(core::Invocation _) → dynamic {}
  no-such-method-forwarder get bar() → core::int
    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))){(core::Invocation) → dynamic} as{TypeError,ForDynamic} core::int;
  no-such-method-forwarder method /* signature-type: (core::int, {y: core::String, z: core::double}) → void */ baz(core::int x, {core::String? y = #C1, core::double? z = #C1}) → void
    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C7: y, #C8: z}))){(core::Invocation) → dynamic};
  no-such-method-forwarder set foo(core::int value) → void
    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))){(core::Invocation) → dynamic};
}
class C extends self::B {
  synthetic constructor •() → self::C
    : super self::B::•()
    ;
}
class E extends core::Object implements for::D {
  synthetic constructor •() → self::E
    : super core::Object::•()
    ;
  no-such-method-forwarder get _privateField() → core::int
    return throw{for-error-handling} core::NoSuchMethodError::withInvocation(this, new core::_InvocationMirror::_withType(#C10, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
  no-such-method-forwarder set _privateField(core::int value) → void
    return throw{for-error-handling} core::NoSuchMethodError::withInvocation(this, new core::_InvocationMirror::_withType(#C11, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
  no-such-method-forwarder get _privateGetter() → core::int
    return throw{for-error-handling} core::NoSuchMethodError::withInvocation(this, new core::_InvocationMirror::_withType(#C12, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
  no-such-method-forwarder method _privateMethod() → void
    return throw{for-error-handling} core::NoSuchMethodError::withInvocation(this, new core::_InvocationMirror::_withType(#C13, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
  no-such-method-forwarder set _privateSetter(core::int value) → void
    return throw{for-error-handling} core::NoSuchMethodError::withInvocation(this, new core::_InvocationMirror::_withType(#C14, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
}
class F extends self::E {
  synthetic constructor •() → self::F
    : super self::E::•()
    ;
}
static method main() → dynamic {}

library;
//
// Problems in library:
//
// pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation_lib.dart:6:7: Error: Field '_privateField' should be initialized because its type 'int' doesn't allow null.
//   int _privateField;
//       ^^^^^^^^^^^^^
//
import self as for;
import "dart:core" as core;

abstract class D extends core::Object {
  field core::int _privateField = null;
  synthetic constructor •() → for::D
    : super core::Object::•()
    ;
  abstract get _privateGetter() → core::int;
  abstract set _privateSetter(core::int value) → void;
  abstract method _privateMethod() → void;
}

constants  {
  #C1 = null
  #C2 = #bar
  #C3 = <core::Type*>[]
  #C4 = <dynamic>[]
  #C5 = <core::Symbol*, dynamic>{}
  #C6 = #baz
  #C7 = #y
  #C8 = #z
  #C9 = #foo=
  #C10 = #org-dartlang-testcase:///forwarder_propagation.dart::_privateField
  #C11 = #org-dartlang-testcase:///forwarder_propagation.dart::_privateField=
  #C12 = #org-dartlang-testcase:///forwarder_propagation.dart::_privateGetter
  #C13 = #org-dartlang-testcase:///forwarder_propagation.dart::_privateMethod
  #C14 = #org-dartlang-testcase:///forwarder_propagation.dart::_privateSetter=
}
