[kernel] Add new member kind for redirecting factory constructors

New type of AST nodes RedirectingFactoryConstructor is added to Kernel.
The goal is to keep the information about redirecting factory
constructors in the class for the linking phase.

Change-Id: I7477c617fa7fd4935ceb23098ec7c056d1f286ca
Reviewed-on: https://dart-review.googlesource.com/14740
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index 2f36e25..1f3cac4 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -387,6 +387,8 @@
 rasta/unresolved_for_in: Crash
 rasta/unresolved_recovery: Crash
 redirecting_factory: Crash
+redirecting_factory_typeparam_test: Crash
+redirecting_factory_typeparambounds_test: Crash
 regress/issue_29937: Crash
 regress/issue_29941: Crash
 regress/issue_29942: Crash
diff --git a/pkg/front_end/testcases/compile.status b/pkg/front_end/testcases/compile.status
index 607685e..42ac1df 100644
--- a/pkg/front_end/testcases/compile.status
+++ b/pkg/front_end/testcases/compile.status
@@ -18,6 +18,11 @@
 named_parameters: Fail # Missing types and unnecessary default values.
 optional: Fail # Unnecessary default values.
 redirecting_factory: Fail # Missing types on constructor parameters.
+redirecting_factory_chain_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_simple_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeargs_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparam_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparambounds_test: VerificationError # Incorrect references to class type parameters. Missing support for RedirectingFactoryConstructor.
 statements: Fail # Make async tranformer optional for golden file testing.
 type_variable_as_super: Fail
 uninitialized_fields: Fail # Fasta and dartk disagree on static initializers
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 4d31e00..ba3b18d 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -3,6 +3,11 @@
 # BSD-style license that can be found in the LICENSE.md file.
 
 incomplete_field_formal_parameter: Fail # Fasta doesn't recover well
+redirecting_factory_chain_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_simple_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeargs_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparam_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparambounds_test: VerificationError # Incorrect references to class type parameters. Missing support for RedirectingFactoryConstructor.
 
 inference/async_closure_return_type_flatten: Fail
 inference/async_closure_return_type_future: Fail
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart b/pkg/front_end/testcases/redirecting_factory_chain_test.dart
new file mode 100644
index 0000000..ad9409e
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to check the representation of redirecting
+// factory constructors in a case of a redirecting chain.
+
+library redirecting_factory_constructors.chain_test;
+
+class A {
+  A();
+  factory A.first() = A;
+  factory A.second() = A.first;
+}
+
+main() {
+  new A.second();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.direct.expect
new file mode 100644
index 0000000..8d9ab57
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.direct.expect
@@ -0,0 +1,14 @@
+library redirecting_factory_constructors.chain_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory first() = self::A::•;
+  factory second() = self::A::first;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.outline.expect
new file mode 100644
index 0000000..c8fde7b
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.outline.expect
@@ -0,0 +1,12 @@
+library redirecting_factory_constructors.chain_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    ;
+  factory first() = self::A::•;
+  factory second() = self::A::first;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect
new file mode 100644
index 0000000..8d9ab57
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_chain_test.dart.strong.expect
@@ -0,0 +1,14 @@
+library redirecting_factory_constructors.chain_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory first() = self::A::•;
+  factory second() = self::A::first;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart b/pkg/front_end/testcases/redirecting_factory_simple_test.dart
new file mode 100644
index 0000000..0598023
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to check the representation of redirecting
+// factory constructors on a simple case.
+
+library redirecting_factory_constructors.simple_test;
+
+class A {
+  A();
+  factory A.redir() = A;
+}
+
+main() {
+  new A.redir();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.direct.expect
new file mode 100644
index 0000000..76c0f44
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.direct.expect
@@ -0,0 +1,13 @@
+library redirecting_factory_constructors.simple_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory redir() = self::A::•;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.outline.expect
new file mode 100644
index 0000000..c7b7c78
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.outline.expect
@@ -0,0 +1,11 @@
+library redirecting_factory_constructors.simple_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    ;
+  factory redir() = self::A::•;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect
new file mode 100644
index 0000000..76c0f44
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_simple_test.dart.strong.expect
@@ -0,0 +1,13 @@
+library redirecting_factory_constructors.simple_test;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory redir() = self::A::•;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart
new file mode 100644
index 0000000..611df4c
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to check the representation of redirecting
+// factory constructors in the case when the redirection target has type
+// arguments supplied by the redirecting factory constructor.
+
+library redirecting_factory_constructors.typeargs_test;
+
+class X {}
+
+class Y extends X {}
+
+class A {
+  A();
+
+  factory A.redir() = B<Y>;
+}
+
+class B<T extends X> extends A {
+  B();
+}
+
+main() {
+  new A.redir();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.direct.expect
new file mode 100644
index 0000000..66c4e8a
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.direct.expect
@@ -0,0 +1,28 @@
+library redirecting_factory_constructors.typeargs_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    : super self::X::•()
+    ;
+}
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory redir() = self::B::•<self::Y>;
+}
+class B<T extends self::X> extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•<self::Y>();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.outline.expect
new file mode 100644
index 0000000..95ab8bf
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.outline.expect
@@ -0,0 +1,23 @@
+library redirecting_factory_constructors.typeargs_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    ;
+}
+class A extends core::Object {
+  constructor •() → void
+    ;
+  factory redir() = self::B::•<self::Y>;
+}
+class B<T extends self::X> extends self::A {
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect
new file mode 100644
index 0000000..66c4e8a
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeargs_test.dart.strong.expect
@@ -0,0 +1,28 @@
+library redirecting_factory_constructors.typeargs_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    : super self::X::•()
+    ;
+}
+class A extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+  factory redir() = self::B::•<self::Y>;
+}
+class B<T extends self::X> extends self::A {
+  constructor •() → void
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  new self::B::•<self::Y>();
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart
new file mode 100644
index 0000000..967771f
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to check the representation of redirecting
+// factory constructors in the case when type parameters of the enclosing class
+// are used in type annotations of the parameters of the redirecting factory
+// constructor.
+
+library redirecting_factory_constructors.typeparam_test;
+
+class A<T, S> {
+  A(T t, S s);
+  factory A.redir(T t, S s) = A<T, S>;
+}
+
+main() {
+  new A<int, String>.redir(42, "foobar");
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.direct.expect
new file mode 100644
index 0000000..ed3508e
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.direct.expect
@@ -0,0 +1,13 @@
+library redirecting_factory_constructors.typeparam_test;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object, S extends core::Object> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    : super core::Object::•()
+    ;
+  factory redir<T extends core::Object, S extends core::Object>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic {
+  new self::A::•<core::int, core::String>(42, "foobar");
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.outline.expect
new file mode 100644
index 0000000..6c99e66
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.outline.expect
@@ -0,0 +1,11 @@
+library redirecting_factory_constructors.typeparam_test;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object, S extends core::Object> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    ;
+  factory redir<T extends core::Object, S extends core::Object>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect
new file mode 100644
index 0000000..ed3508e
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparam_test.dart.strong.expect
@@ -0,0 +1,13 @@
+library redirecting_factory_constructors.typeparam_test;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object, S extends core::Object> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    : super core::Object::•()
+    ;
+  factory redir<T extends core::Object, S extends core::Object>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic {
+  new self::A::•<core::int, core::String>(42, "foobar");
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart
new file mode 100644
index 0000000..102c03a
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The purpose of this test is to check the representation of redirecting
+// factory constructors in the case when type parameters of the enclosing class
+// are used in type annotations of the parameters of the redirecting factory
+// constructor, and one of the type parameters is the upper bound for the other.
+
+library redirecting_factory_constructors.typeparambounds_test;
+
+class X {}
+
+class Y extends X {}
+
+class A<T, S extends T> {
+  A(T t, S s);
+  factory A.redir(T t, S s) = A<T, S>;
+}
+
+main() {
+  new A<X, Y>.redir(new X(), new Y());
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.direct.expect
new file mode 100644
index 0000000..f87c110
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.direct.expect
@@ -0,0 +1,23 @@
+library redirecting_factory_constructors.typeparambounds_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    : super self::X::•()
+    ;
+}
+class A<T extends core::Object, S extends self::A::T> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    : super core::Object::•()
+    ;
+  factory redir<T extends core::Object, S extends T>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic {
+  new self::A::•<self::X, self::Y>(new self::X::•(), new self::Y::•());
+}
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.outline.expect
new file mode 100644
index 0000000..27dc65e
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.outline.expect
@@ -0,0 +1,19 @@
+library redirecting_factory_constructors.typeparambounds_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    ;
+}
+class A<T extends core::Object, S extends self::A::T> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    ;
+  factory redir<T extends core::Object, S extends T>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect
new file mode 100644
index 0000000..f87c110
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_factory_typeparambounds_test.dart.strong.expect
@@ -0,0 +1,23 @@
+library redirecting_factory_constructors.typeparambounds_test;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+  default constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class Y extends self::X {
+  default constructor •() → void
+    : super self::X::•()
+    ;
+}
+class A<T extends core::Object, S extends self::A::T> extends core::Object {
+  constructor •(self::A::T t, self::A::S s) → void
+    : super core::Object::•()
+    ;
+  factory redir<T extends core::Object, S extends T>(T t, S s) = self::A::•<T, S>;
+}
+static method main() → dynamic {
+  new self::A::•<self::X, self::Y>(new self::X::•(), new self::Y::•());
+}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 39b18c6..a4b955f 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -46,6 +46,11 @@
 prefer_baseclass: Fail
 redirecting_constructor: Fail
 redirecting_factory: Fail
+redirecting_factory_chain_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_simple_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeargs_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparam_test: Fail # Missing support for RedirectingFactoryConstructor.
+redirecting_factory_typeparambounds_test: VerificationError # Incorrect references to class type parameters. Missing support for RedirectingFactoryConstructor.
 statements: Fail
 stringliteral: Fail
 super_rasta_copy: TypeCheckError
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 71b8ef1..dc2d7ba 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -293,6 +293,7 @@
   List<Field> fields;
   List<Constructor> constructors;
   List<Procedure> procedures;
+  List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
 
   // Class index. Offsets are used to get start (inclusive) and end (exclusive) byte positions for
   // a specific procedure. Note the "+1" to account for needing the end of the last entry.
@@ -356,6 +357,23 @@
   Option<FunctionNode> function;
 }
 
+type RedirectingFactoryConstructor extends Member {
+  Byte tag = 107;
+  CanonicalNameReference canonicalName;
+  FileOffset fileOffset;
+  FileOffset fileEndOffset;
+  Byte flags;
+  Name name;
+  List<Expression> annotations;
+  List<DartType> typeArguments;
+  MemberReference targetReference;
+  List<TypeParameter> typeParameters;
+  UInt parameterCount; // positionalParameters.length + namedParameters.length.
+  UInt requiredParameterCount;
+  List<VariableDeclaration> positionalParameters;
+  List<VariableDeclaration> namedParameters;
+}
+
 abstract type Initializer extends Node {}
 
 type InvalidInitializer extends Initializer {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index f10864f..e8df344 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -730,6 +730,11 @@
   /// For mixin applications this should only contain forwarding stubs.
   final List<Procedure> procedures;
 
+  /// Redirecting factory constructors declared in the class.
+  ///
+  /// For mixin applications this should be empty.
+  final List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
+
   Class(
       {this.name,
       this.isAbstract: false,
@@ -741,6 +746,7 @@
       List<Constructor> constructors,
       List<Procedure> procedures,
       List<Field> fields,
+      List<RedirectingFactoryConstructor> redirectingFactoryConstructors,
       this.fileUri,
       Reference reference})
       : this.typeParameters = typeParameters ?? <TypeParameter>[],
@@ -748,11 +754,14 @@
         this.fields = fields ?? <Field>[],
         this.constructors = constructors ?? <Constructor>[],
         this.procedures = procedures ?? <Procedure>[],
+        this.redirectingFactoryConstructors =
+            redirectingFactoryConstructors ?? <RedirectingFactoryConstructor>[],
         super(reference) {
     setParents(this.typeParameters, this);
     setParents(this.constructors, this);
     setParents(this.procedures, this);
     setParents(this.fields, this);
+    setParents(this.redirectingFactoryConstructors, this);
   }
 
   void computeCanonicalNames() {
@@ -766,6 +775,9 @@
     for (var member in constructors) {
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
+    for (var member in redirectingFactoryConstructors) {
+      canonicalName.getChildFromMember(member).bindTo(member.reference);
+    }
   }
 
   /// The immediate super class, or `null` if this is the root class.
@@ -786,8 +798,12 @@
   ///
   /// This getter is for convenience, not efficiency.  Consider manually
   /// iterating the members to speed up code in production.
-  Iterable<Member> get members =>
-      <Iterable<Member>>[fields, constructors, procedures].expand((x) => x);
+  Iterable<Member> get members => <Iterable<Member>>[
+        fields,
+        constructors,
+        procedures,
+        redirectingFactoryConstructors
+      ].expand((x) => x);
 
   /// The immediately extended, mixed-in, and implemented types.
   ///
@@ -814,6 +830,8 @@
       procedures.add(member);
     } else if (member is Field) {
       fields.add(member);
+    } else if (member is RedirectingFactoryConstructor) {
+      redirectingFactoryConstructors.add(member);
     } else {
       throw new ArgumentError(member);
     }
@@ -877,6 +895,7 @@
     visitList(constructors, v);
     visitList(procedures, v);
     visitList(fields, v);
+    visitList(redirectingFactoryConstructors, v);
   }
 
   transformChildren(Transformer v) {
@@ -892,6 +911,7 @@
     transformList(constructors, v, this);
     transformList(procedures, v, this);
     transformList(fields, v, this);
+    transformList(redirectingFactoryConstructors, v, this);
   }
 
   Location _getLocationInEnclosingFile(int offset) {
@@ -1265,6 +1285,148 @@
   DartType get setterType => const BottomType();
 }
 
+/// Residue of a redirecting factory constructor for the linking phase.
+///
+/// In the following example, `bar` is a redirecting factory constructor.
+///
+///     class A {
+///       A.foo();
+///       factory A.bar() = A.foo;
+///     }
+///
+/// An invocation of `new A.bar()` has the same effect as an invocation of
+/// `new A.foo()`.  In Kernel, the invocations of `bar` are replaced with
+/// invocations of `foo`, and after it is done, the redirecting constructor can
+/// be removed from the class.  However, it is needed during the linking phase,
+/// because other modules can refer to that constructor.
+///
+/// [RedirectingFactoryConstructor]s contain the necessary information for
+/// linking and are treated as non-runnable members of classes that merely serve
+/// as containers for that information.
+///
+/// Existing transformers may easily ignore [RedirectingFactoryConstructor]s,
+/// because the class is implemented as a subclass of [Member], and not as a
+/// subclass of, for example, [Constructor] or [Procedure].
+///
+/// Redirecting factory constructors can be unnamed.  In this case, the name is
+/// an empty string (in a [Name]).
+class RedirectingFactoryConstructor extends Member {
+  int flags = 0;
+
+  /// [RedirectingFactoryConstructor]s may redirect to constructors or factories
+  /// of instantiated generic types, that is, generic types with supplied type
+  /// arguments.  The supplied type arguments are stored in this field.
+  final List<DartType> typeArguments;
+
+  /// Reference to the constructor or the factory that this
+  /// [RedirectingFactoryConstructor] redirects to.
+  Reference targetReference;
+
+  /// [typeParameters] are duplicates of the type parameters of the enclosing
+  /// class.  Because [RedirectingFactoryConstructor]s aren't instance members,
+  /// references to the type parameters of the enclosing class in the
+  /// redirection target description are encoded with references to the elements
+  /// of [typeParameters].
+  List<TypeParameter> typeParameters;
+
+  /// Positional parameters of [RedirectingFactoryConstructor]s should be
+  /// compatible with that of the target constructor.
+  List<VariableDeclaration> positionalParameters;
+  int requiredParameterCount;
+
+  /// Named parameters of [RedirectingFactoryConstructor]s should be compatible
+  /// with that of the target constructor.
+  List<VariableDeclaration> namedParameters;
+
+  RedirectingFactoryConstructor(this.targetReference,
+      {Name name,
+      bool isConst: false,
+      bool isExternal: false,
+      bool isSyntheticDefault: false,
+      int transformerFlags: 0,
+      List<DartType> typeArguments,
+      List<TypeParameter> typeParameters,
+      List<VariableDeclaration> positionalParameters,
+      List<VariableDeclaration> namedParameters,
+      int requiredParameterCount,
+      Reference reference})
+      : this.typeArguments = typeArguments ?? <DartType>[],
+        this.typeParameters = typeParameters ?? <TypeParameter>[],
+        this.positionalParameters =
+            positionalParameters ?? <VariableDeclaration>[],
+        this.namedParameters = namedParameters ?? <VariableDeclaration>[],
+        this.requiredParameterCount =
+            requiredParameterCount ?? positionalParameters?.length ?? 0,
+        super(name, reference) {
+    setParents(this.typeParameters, this);
+    setParents(this.positionalParameters, this);
+    setParents(this.namedParameters, this);
+    this.isConst = isConst;
+    this.isExternal = isExternal;
+    this.isSyntheticDefault = isSyntheticDefault;
+    this.transformerFlags = transformerFlags;
+  }
+
+  static const int FlagConst = 1 << 0; // Must match serialized bit positions.
+  static const int FlagExternal = 1 << 1;
+  static const int FlagSyntheticDefault = 1 << 2;
+
+  bool get isConst => flags & FlagConst != 0;
+  bool get isExternal => flags & FlagExternal != 0;
+
+  /// True if this is a synthetic default constructor inserted in a class that
+  /// does not otherwise declare any constructors.
+  bool get isSyntheticDefault => flags & FlagSyntheticDefault != 0;
+
+  void set isConst(bool value) {
+    flags = value ? (flags | FlagConst) : (flags & ~FlagConst);
+  }
+
+  void set isExternal(bool value) {
+    flags = value ? (flags | FlagExternal) : (flags & ~FlagExternal);
+  }
+
+  void set isSyntheticDefault(bool value) {
+    flags = value
+        ? (flags | FlagSyntheticDefault)
+        : (flags & ~FlagSyntheticDefault);
+  }
+
+  bool get isInstanceMember => false;
+  bool get hasGetter => false;
+  bool get hasSetter => false;
+
+  bool get isUnresolved => targetReference == null;
+
+  Member get target => targetReference?.asMember;
+
+  void set target(Member member) {
+    assert(member is Constructor ||
+        (member is Procedure && member.kind == ProcedureKind.Factory));
+    targetReference = getMemberReference(member);
+  }
+
+  accept(MemberVisitor v) => v.visitRedirectingFactoryConstructor(this);
+
+  acceptReference(MemberReferenceVisitor v) =>
+      v.visitRedirectingFactoryConstructorReference(this);
+
+  visitChildren(Visitor v) {
+    visitList(annotations, v);
+    target?.acceptReference(v);
+    visitList(typeArguments, v);
+    name?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    transformList(annotations, v, this);
+    transformTypeList(typeArguments, v);
+  }
+
+  DartType get getterType => const BottomType();
+  DartType get setterType => const BottomType();
+}
+
 /// A method, getter, setter, index-getter, index-setter, operator overloader,
 /// or factory.
 ///
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 006b265..12010e8 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -797,6 +797,8 @@
       return readProcedure(procedureOffsets[index + 1]);
     }, node);
     _byteOffset = procedureOffsets.last;
+    _mergeNamedNodeList(node.redirectingFactoryConstructors,
+        (index) => readRedirectingFactoryConstructor(), node);
     typeParameterStack.length = 0;
     assert(debugPath.removeLast() != null);
     if (shouldWriteData) {
@@ -943,6 +945,50 @@
     return node;
   }
 
+  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+    int tag = readByte();
+    assert(tag == Tag.RedirectingFactoryConstructor);
+    var canonicalName = readCanonicalNameReference();
+    var reference = canonicalName.getReference();
+    RedirectingFactoryConstructor node = reference.node;
+    bool shouldWriteData = node == null || _isReadingLibraryImplementation;
+    if (node == null) {
+      node = new RedirectingFactoryConstructor(null, reference: reference);
+    }
+    var fileOffset = readOffset();
+    var fileEndOffset = readOffset();
+    var flags = readByte();
+    var name = readName();
+    var annotations = readAnnotationList(node);
+    debugPath.add(node.name?.name ?? 'redirecting-factory-constructor');
+    var targetReference = readMemberReference();
+    var typeArguments = readDartTypeList();
+    int typeParameterStackHeight = typeParameterStack.length;
+    var typeParameters = readAndPushTypeParameterList();
+    readUInt(); // Total parameter count.
+    var requiredParameterCount = readUInt();
+    int variableStackHeight = variableStack.length;
+    var positional = readAndPushVariableDeclarationList();
+    var named = readAndPushVariableDeclarationList();
+    variableStack.length = variableStackHeight;
+    typeParameterStack.length = typeParameterStackHeight;
+    debugPath.removeLast();
+    if (shouldWriteData) {
+      node.fileOffset = fileOffset;
+      node.fileEndOffset = fileEndOffset;
+      node.flags = flags;
+      node.name = name;
+      node.annotations = annotations;
+      node.targetReference = targetReference;
+      node.typeArguments.addAll(typeArguments);
+      node.typeParameters = typeParameters;
+      node.requiredParameterCount = requiredParameterCount;
+      node.positionalParameters = positional;
+      node.namedParameters = named;
+    }
+    return node;
+  }
+
   Initializer readInitializer() {
     int tag = readByte();
     bool isSynthetic = readByte() == 1;
@@ -1915,6 +1961,13 @@
   }
 
   @override
+  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+    final nodeOffset = _byteOffset;
+    final result = super.readRedirectingFactoryConstructor();
+    return _associateMetadata(result, nodeOffset);
+  }
+
+  @override
   Initializer readInitializer() {
     final nodeOffset = _byteOffset;
     final result = super.readInitializer();
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 07ff414..48f5412 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -703,6 +703,7 @@
     procedureOffsets = <int>[];
     writeNodeList(node.procedures);
     procedureOffsets.add(getBufferOffset());
+    writeNodeList(node.redirectingFactoryConstructors);
     _typeParameterIndexer.exit(node.typeParameters);
 
     assert(procedureOffsets.length > 0);
@@ -774,6 +775,32 @@
     _variableIndexer = null;
   }
 
+  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    if (node.canonicalName == null) {
+      throw 'Missing canonical name for $node';
+    }
+    writeByte(Tag.RedirectingFactoryConstructor);
+    _variableIndexer = new VariableIndexer();
+    _variableIndexer.pushScope();
+    _typeParameterIndexer.enter(node.typeParameters);
+    writeCanonicalNameReference(getCanonicalNameOfMember(node));
+    writeOffset(node.fileOffset);
+    writeOffset(node.fileEndOffset);
+    writeByte(node.flags);
+    writeName(node.name);
+    writeAnnotationList(node.annotations);
+    writeReference(node.targetReference);
+    writeNodeList(node.typeArguments);
+    writeNodeList(node.typeParameters);
+    writeUInt30(node.positionalParameters.length + node.namedParameters.length);
+    writeUInt30(node.requiredParameterCount);
+    writeVariableDeclarationList(node.positionalParameters);
+    writeVariableDeclarationList(node.namedParameters);
+    _typeParameterIndexer.exit(node.typeParameters);
+    _variableIndexer.popScope();
+    _variableIndexer = null;
+  }
+
   visitInvalidInitializer(InvalidInitializer node) {
     writeByte(Tag.InvalidInitializer);
     writeByte(node.isSynthetic ? 1 : 0);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 6ece984..2583f775 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -14,6 +14,7 @@
   static const int Field = 4;
   static const int Constructor = 5;
   static const int Procedure = 6;
+  static const int RedirectingFactoryConstructor = 108;
 
   static const int InvalidInitializer = 7;
   static const int FieldInitializer = 8;
@@ -115,6 +116,8 @@
 
   static const int ConstantExpression = 107;
 
+  // Note that 108 is occupied by [RedirectingFactoryConstructor] above.
+
   static const int SpecializedTagHighBit = 0x80; // 10000000
   static const int SpecializedTagMask = 0xF8; // 11111000
   static const int SpecializedPayloadMask = 0x7; // 00000111
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 0ef7066..4aa9003 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -194,6 +194,9 @@
     if (member is Constructor) {
       return '@constructors';
     }
+    if (member is RedirectingFactoryConstructor) {
+      return '@factories';
+    }
     throw 'Unexpected member: $member';
   }
 }
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index f94897a..661f630 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -419,6 +419,20 @@
       ..fileEndOffset = node.fileEndOffset;
   }
 
+  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    return new RedirectingFactoryConstructor(node.targetReference,
+        name: node.name,
+        isConst: node.isConst,
+        isExternal: node.isExternal,
+        isSyntheticDefault: node.isSyntheticDefault,
+        transformerFlags: node.transformerFlags,
+        typeArguments: node.typeArguments.map(visitType).toList(),
+        typeParameters: node.typeParameters.map(clone).toList(),
+        positionalParameters: node.positionalParameters.map(clone).toList(),
+        namedParameters: node.namedParameters.map(clone).toList(),
+        requiredParameterCount: node.requiredParameterCount);
+  }
+
   visitTypeParameter(TypeParameter node) {
     var newNode = new TypeParameter(node.name);
     typeSubstitution[node] = new TypeParameterType(newNode);
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 9a78154..3551768 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -926,6 +926,30 @@
         name: node.name, initializers: node.initializers);
   }
 
+  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    writeAnnotationList(node.annotations);
+    writeIndentation();
+    writeModifier(node.isExternal, 'external');
+    writeModifier(node.isConst, 'const');
+    writeModifier(node.isSyntheticDefault, 'default');
+    writeWord('factory');
+
+    if (node.name != null) {
+      writeName(node.name);
+    }
+    writeTypeParameterList(node.typeParameters);
+    writeParameterList(node.positionalParameters, node.namedParameters,
+        node.requiredParameterCount);
+    writeSpaced('=');
+    writeMemberReferenceFromReference(node.targetReference);
+    if (node.typeArguments.isNotEmpty) {
+      writeSymbol('<');
+      writeList(node.typeArguments, writeType);
+      writeSymbol('>');
+    }
+    endLine(';');
+  }
+
   visitClass(Class node) {
     writeAnnotationList(node.annotations);
     writeIndentation();
@@ -955,6 +979,7 @@
     node.fields.forEach(writeNode);
     node.constructors.forEach(writeNode);
     node.procedures.forEach(writeNode);
+    node.redirectingFactoryConstructors.forEach(writeNode);
     --indentation;
     writeIndentation();
     endLine('}');
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index cddbe31..ba0d04b 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -196,6 +196,11 @@
     handleFunctionNode(node.function);
   }
 
+  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    environment.returnType = null;
+    environment.yieldType = null;
+  }
+
   void handleFunctionNode(FunctionNode node) {
     var oldAsyncMarker = environment.currentAsyncMarker;
     environment.currentAsyncMarker = node.asyncMarker;
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 7287c69..2c45328 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -103,6 +103,9 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
+  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    return defaultMember(node);
+  }
 }
 
 abstract class InitializerVisitor<R> {
@@ -216,6 +219,9 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
+  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    return defaultMember(node);
+  }
 
   // Classes
   R visitClass(Class node) => defaultTreeNode(node);
@@ -283,6 +289,10 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
+  R visitRedirectingFactoryConstructorReference(
+      RedirectingFactoryConstructor node) {
+    return defaultMemberReference(node);
+  }
 }
 
 class Visitor<R> extends TreeVisitor<R>
@@ -353,6 +363,10 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
+  R visitRedirectingFactoryConstructorReference(
+      RedirectingFactoryConstructor node) {
+    return defaultMemberReference(node);
+  }
 
   R visitName(Name node) => defaultNode(node);
   R visitSupertype(Supertype node) => defaultNode(node);