[fasta] Report instantiate-to-bound failure due to non-simple bounds

Fixes #33208, #31810, #32416, #32417

Bug: http://dartbug.com/33208
Bug: http://dartbug.com/31810
Bug: http://dartbug.com/32416
Bug: http://dartbug.com/32417
Change-Id: Id178daf35be459fdefe04091bf929b5743d89e81
Reviewed-on: https://dart-review.googlesource.com/41264
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart b/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
index c0d57e5..f594ed6 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
@@ -1400,16 +1400,6 @@
   }
 
   @failingTest
-  test_typedef_type_parameters_bound_recursive() async {
-    await super.test_typedef_type_parameters_bound_recursive();
-  }
-
-  @failingTest
-  test_typedef_type_parameters_bound_recursive2() async {
-    await super.test_typedef_type_parameters_bound_recursive2();
-  }
-
-  @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/30267')
   test_unresolved_annotation_instanceCreation_argument_super() async {
     await super.test_unresolved_annotation_instanceCreation_argument_super();
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 9775410..49496f9 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -215,6 +215,96 @@
     message: r"""'await' can only be used in 'async' or 'async*' methods.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateBoundIssueViaCycleNonSimplicity = const Template<
+        Message Function(String name,
+            String name2)>(
+    messageTemplate:
+        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '#name2'.""",
+    tipTemplate:
+        r"""Try providing type arguments to '#name2' here or to some other raw types in the bounds along the reference chain.""",
+    withArguments: _withArgumentsBoundIssueViaCycleNonSimplicity);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeBoundIssueViaCycleNonSimplicity =
+    const Code<Message Function(String name, String name2)>(
+        "BoundIssueViaCycleNonSimplicity",
+        templateBoundIssueViaCycleNonSimplicity,
+        analyzerCode: "STRONG_MODE_NOT_INSTANTIATED_BOUND",
+        dart2jsCode: "*fatal*",
+        severity: Severity.error);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBoundIssueViaCycleNonSimplicity(
+    String name, String name2) {
+  return new Message(codeBoundIssueViaCycleNonSimplicity,
+      message:
+          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '${name2}'.""",
+      tip: """Try providing type arguments to '${name2}' here or to some other raw types in the bounds along the reference chain.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateBoundIssueViaLoopNonSimplicity = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables.""",
+    tipTemplate: r"""Try providing type arguments to '#name' here.""",
+    withArguments: _withArgumentsBoundIssueViaLoopNonSimplicity);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeBoundIssueViaLoopNonSimplicity =
+    const Code<Message Function(String name)>("BoundIssueViaLoopNonSimplicity",
+        templateBoundIssueViaLoopNonSimplicity,
+        analyzerCode: "STRONG_MODE_NOT_INSTANTIATED_BOUND",
+        dart2jsCode: "*fatal*",
+        severity: Severity.error);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBoundIssueViaLoopNonSimplicity(String name) {
+  return new Message(codeBoundIssueViaLoopNonSimplicity,
+      message:
+          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables.""",
+      tip: """Try providing type arguments to '${name}' here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateBoundIssueViaRawTypeWithNonSimpleBounds =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Generic type '#name' can't be used without type arguments in a type variable bound.""",
+        tipTemplate: r"""Try providing type arguments to '#name' here.""",
+        withArguments: _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeBoundIssueViaRawTypeWithNonSimpleBounds =
+    const Code<Message Function(String name)>(
+        "BoundIssueViaRawTypeWithNonSimpleBounds",
+        templateBoundIssueViaRawTypeWithNonSimpleBounds,
+        analyzerCode: "STRONG_MODE_NOT_INSTANTIATED_BOUND",
+        dart2jsCode: "*fatal*",
+        severity: Severity.error);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds(String name) {
+  return new Message(codeBoundIssueViaRawTypeWithNonSimpleBounds,
+      message:
+          """Generic type '${name}' can't be used without type arguments in a type variable bound.""",
+      tip: """Try providing type arguments to '${name}' here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeBreakOutsideOfLoop = messageBreakOutsideOfLoop;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4541,6 +4631,51 @@
         r"""Try removing the other directives, or moving them to the library for which this is a part.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateNonSimpleBoundViaReference =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Bound of this variable references raw type '#name'.""",
+        withArguments: _withArgumentsNonSimpleBoundViaReference);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeNonSimpleBoundViaReference =
+    const Code<Message Function(String name)>(
+        "NonSimpleBoundViaReference", templateNonSimpleBoundViaReference,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonSimpleBoundViaReference(String name) {
+  return new Message(codeNonSimpleBoundViaReference,
+      message: """Bound of this variable references raw type '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateNonSimpleBoundViaVariable = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Bound of this variable references variable '#name' from the same declaration.""",
+    withArguments: _withArgumentsNonSimpleBoundViaVariable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeNonSimpleBoundViaVariable =
+    const Code<Message Function(String name)>(
+        "NonSimpleBoundViaVariable", templateNonSimpleBoundViaVariable,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonSimpleBoundViaVariable(String name) {
+  return new Message(codeNonSimpleBoundViaVariable,
+      message:
+          """Bound of this variable references variable '${name}' from the same declaration.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 5b4cbf3..cc5a316 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -33,6 +33,7 @@
 
 import '../fasta_codes.dart'
     show
+        LocatedMessage,
         Message,
         messageConflictsWithTypeVariableCause,
         messageTypeVariableDuplicatedName,
@@ -99,6 +100,7 @@
         QualifiedName,
         Scope,
         TypeBuilder,
+        TypeDeclarationBuilder,
         TypeVariableBuilder,
         UnresolvedType,
         VoidTypeBuilder,
@@ -107,7 +109,11 @@
 
 import 'metadata_collector.dart';
 
-import 'type_algorithms.dart' show calculateBounds;
+import 'type_algorithms.dart'
+    show
+        calculateBounds,
+        getNonSimplicityIssuesForDeclaration,
+        getNonSimplicityIssuesForTypeVariables;
 
 class KernelLibraryBuilder
     extends SourceLibraryBuilder<KernelTypeBuilder, Library> {
@@ -1037,32 +1043,79 @@
   int computeDefaultTypes(TypeBuilder dynamicType, TypeBuilder bottomType,
       ClassBuilder objectClass) {
     int count = 0;
-    bool strongMode = loader.target.strongMode;
 
-    int computeDefaultTypesForVariables(List<TypeVariableBuilder> variables) {
+    int computeDefaultTypesForVariables(
+        List<TypeVariableBuilder<TypeBuilder, Object>> variables,
+        bool strongMode) {
       if (variables == null) return 0;
-      List<KernelTypeBuilder> calculatedBounds = strongMode
-          ? calculateBounds(variables, dynamicType, bottomType, objectClass)
-          : null;
-      for (int i = 0; i < variables.length; ++i) {
-        variables[i].defaultType =
-            strongMode ? calculatedBounds[i] : dynamicType;
+
+      if (strongMode) {
+        List<KernelTypeBuilder> calculatedBounds =
+            calculateBounds(variables, dynamicType, bottomType, objectClass);
+        for (int i = 0; i < variables.length; ++i) {
+          variables[i].defaultType = calculatedBounds[i];
+        }
+      } else {
+        // In Dart 1, put `dynamic` everywhere.
+        for (int i = 0; i < variables.length; ++i) {
+          variables[i].defaultType = dynamicType;
+        }
       }
+
       return variables.length;
     }
 
+    void reportIssues(List<Object> issues) {
+      for (int i = 0; i < issues.length; i += 3) {
+        TypeDeclarationBuilder<TypeBuilder, Object> declaration = issues[i];
+        Message message = issues[i + 1];
+        List<LocatedMessage> context = issues[i + 2];
+
+        addProblem(message, declaration.charOffset, declaration.name.length,
+            declaration.fileUri,
+            context: context);
+      }
+    }
+
+    bool strongMode = loader.target.strongMode;
     for (var declaration in libraryDeclaration.members.values) {
       if (declaration is KernelClassBuilder) {
-        count += computeDefaultTypesForVariables(declaration.typeVariables);
+        {
+          List<Object> issues = strongMode
+              ? getNonSimplicityIssuesForDeclaration(declaration)
+              : const <Object>[];
+          reportIssues(issues);
+          // In case of issues, use non-strong mode for error recovery.
+          count += computeDefaultTypesForVariables(
+              declaration.typeVariables, strongMode && issues.length == 0);
+        }
         declaration.forEach((String name, Declaration member) {
           if (member is KernelProcedureBuilder) {
-            count += computeDefaultTypesForVariables(member.typeVariables);
+            List<Object> issues = strongMode
+                ? getNonSimplicityIssuesForTypeVariables(member.typeVariables)
+                : const <Object>[];
+            reportIssues(issues);
+            // In case of issues, use non-strong mode for error recovery.
+            count += computeDefaultTypesForVariables(
+                member.typeVariables, strongMode && issues.length == 0);
           }
         });
       } else if (declaration is KernelFunctionTypeAliasBuilder) {
-        count += computeDefaultTypesForVariables(declaration.typeVariables);
+        List<Object> issues = strongMode
+            ? getNonSimplicityIssuesForDeclaration(declaration)
+            : const <Object>[];
+        reportIssues(issues);
+        // In case of issues, use non-strong mode for error recovery.
+        count += computeDefaultTypesForVariables(
+            declaration.typeVariables, strongMode && issues.length == 0);
       } else if (declaration is KernelFunctionBuilder) {
-        count += computeDefaultTypesForVariables(declaration.typeVariables);
+        List<Object> issues = strongMode
+            ? getNonSimplicityIssuesForTypeVariables(declaration.typeVariables)
+            : const <Object>[];
+        reportIssues(issues);
+        // In case of issues, use non-strong mode for error recovery.
+        count += computeDefaultTypesForVariables(
+            declaration.typeVariables, strongMode && issues.length == 0);
       }
     }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 0f1081f..81b72d7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -2,22 +2,42 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
 
-import 'kernel_builder.dart'
-    show
-        TypeBuilder,
-        TypeVariableBuilder,
-        KernelFormalParameterBuilder,
-        KernelTypeBuilder,
-        KernelNamedTypeBuilder,
-        KernelTypeVariableBuilder,
-        KernelClassBuilder,
-        KernelFunctionTypeBuilder,
-        NamedTypeBuilder,
-        FormalParameterBuilder,
-        FunctionTypeBuilder;
+import 'package:kernel/ast.dart' show TypeParameter;
+
+import 'package:kernel/type_algebra.dart' show containsTypeVariable;
 
 import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
 
+import 'kernel_builder.dart'
+    show
+        ClassBuilder,
+        FormalParameterBuilder,
+        FunctionTypeAliasBuilder,
+        FunctionTypeBuilder,
+        KernelClassBuilder,
+        KernelFormalParameterBuilder,
+        KernelFunctionTypeBuilder,
+        KernelNamedTypeBuilder,
+        KernelTypeBuilder,
+        KernelTypeVariableBuilder,
+        NamedTypeBuilder,
+        TypeBuilder,
+        TypeDeclarationBuilder,
+        TypeVariableBuilder;
+
+import '../dill/dill_class_builder.dart' show DillClassBuilder;
+
+import '../dill/dill_typedef_builder.dart' show DillFunctionTypeAliasBuilder;
+
+import '../fasta_codes.dart'
+    show
+        LocatedMessage,
+        templateBoundIssueViaCycleNonSimplicity,
+        templateBoundIssueViaLoopNonSimplicity,
+        templateBoundIssueViaRawTypeWithNonSimpleBounds,
+        templateNonSimpleBoundViaReference,
+        templateNonSimpleBoundViaVariable;
+
 KernelTypeBuilder substituteRange(
     KernelTypeBuilder type,
     Map<TypeVariableBuilder, KernelTypeBuilder> upperSubstitution,
@@ -236,3 +256,440 @@
     return edges[index];
   }
 }
+
+/// Finds all type builders for [variable] in [type].
+///
+/// Returns list of the found type builders.
+List<NamedTypeBuilder<TypeBuilder, Object>> findVariableUsesInType(
+  TypeVariableBuilder<TypeBuilder, Object> variable,
+  TypeBuilder type,
+) {
+  var uses = <NamedTypeBuilder<TypeBuilder, Object>>[];
+  if (type is NamedTypeBuilder) {
+    if (type.declaration == variable) {
+      uses.add(type);
+    } else {
+      if (type.arguments != null) {
+        for (TypeBuilder argument in type.arguments) {
+          uses.addAll(findVariableUsesInType(variable, argument));
+        }
+      }
+    }
+  } else if (type is FunctionTypeBuilder) {
+    uses.addAll(findVariableUsesInType(variable, type.returnType));
+    if (type.typeVariables != null) {
+      for (TypeVariableBuilder<TypeBuilder, Object> dependentVariable
+          in type.typeVariables) {
+        if (dependentVariable.bound != null) {
+          uses.addAll(
+              findVariableUsesInType(variable, dependentVariable.bound));
+        }
+        if (dependentVariable.defaultType != null) {
+          uses.addAll(
+              findVariableUsesInType(variable, dependentVariable.defaultType));
+        }
+      }
+    }
+    if (type.formals != null) {
+      for (FormalParameterBuilder<TypeBuilder> formal in type.formals) {
+        uses.addAll(findVariableUsesInType(variable, formal.type));
+      }
+    }
+  }
+  return uses;
+}
+
+/// Finds those of [variables] that reference other [variables] in their bounds.
+///
+/// Returns flattened list of pairs.  The first element in the pair is the type
+/// variable builder from [variables] that references other [variables] in its
+/// bound.  The second element in the pair is the list of found references
+/// represented as type builders.
+List<Object> findInboundReferences(
+    List<TypeVariableBuilder<TypeBuilder, Object>> variables) {
+  var variablesAndDependencies = <Object>[];
+  for (TypeVariableBuilder<TypeBuilder, Object> dependent in variables) {
+    var dependencies = <NamedTypeBuilder<TypeBuilder, Object>>[];
+    for (TypeVariableBuilder<TypeBuilder, Object> dependence in variables) {
+      List<NamedTypeBuilder<TypeBuilder, Object>> uses =
+          findVariableUsesInType(dependence, dependent.bound);
+      if (uses.length != 0) {
+        dependencies.addAll(uses);
+      }
+    }
+    if (dependencies.length != 0) {
+      variablesAndDependencies.add(dependent);
+      variablesAndDependencies.add(dependencies);
+    }
+  }
+  return variablesAndDependencies;
+}
+
+/// Finds raw generic types in [type] with inbound references in type variables.
+///
+/// Returns flattened list of pairs.  The first element in the pair is the found
+/// raw generic type.  The second element in the pair is the list of type
+/// variables of that type with inbound references in the format specified in
+/// [findInboundReferences].
+List<Object> findRawTypesWithInboundReferences(TypeBuilder type) {
+  var typesAndDependencies = <Object>[];
+  if (type is NamedTypeBuilder<TypeBuilder, Object>) {
+    if (type.arguments == null) {
+      TypeDeclarationBuilder<TypeBuilder, Object> declaration =
+          type.declaration;
+      if (declaration is DillClassBuilder) {
+        bool hasInbound = false;
+        List<TypeParameter> typeParameters = declaration.target.typeParameters;
+        for (int i = 0; i < typeParameters.length && !hasInbound; ++i) {
+          if (containsTypeVariable(
+              typeParameters[i].bound, typeParameters.toSet())) {
+            hasInbound = true;
+          }
+        }
+        if (hasInbound) {
+          typesAndDependencies.add(type);
+          typesAndDependencies.add(const <Object>[]);
+        }
+      } else if (declaration is DillFunctionTypeAliasBuilder) {
+        bool hasInbound = false;
+        List<TypeParameter> typeParameters = declaration.target.typeParameters;
+        for (int i = 0; i < typeParameters.length && !hasInbound; ++i) {
+          if (containsTypeVariable(
+              typeParameters[i].bound, typeParameters.toSet())) {
+            hasInbound = true;
+          }
+        }
+        if (hasInbound) {
+          typesAndDependencies.add(type);
+          typesAndDependencies.add(const <Object>[]);
+        }
+      } else if (declaration is ClassBuilder<TypeBuilder, Object> &&
+          declaration.typeVariables != null) {
+        List<Object> dependencies =
+            findInboundReferences(declaration.typeVariables);
+        if (dependencies.length != 0) {
+          typesAndDependencies.add(type);
+          typesAndDependencies.add(dependencies);
+        }
+      } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object> &&
+          declaration.typeVariables != null) {
+        List<Object> dependencies =
+            findInboundReferences(declaration.typeVariables);
+        if (dependencies.length != 0) {
+          typesAndDependencies.add(type);
+          typesAndDependencies.add(dependencies);
+        }
+      }
+    } else {
+      for (TypeBuilder argument in type.arguments) {
+        typesAndDependencies
+            .addAll(findRawTypesWithInboundReferences(argument));
+      }
+    }
+  } else if (type is FunctionTypeBuilder) {
+    typesAndDependencies
+        .addAll(findRawTypesWithInboundReferences(type.returnType));
+    if (type.typeVariables != null) {
+      for (TypeVariableBuilder<TypeBuilder, Object> variable
+          in type.typeVariables) {
+        if (variable.bound != null) {
+          typesAndDependencies
+              .addAll(findRawTypesWithInboundReferences(variable.bound));
+        }
+        if (variable.defaultType != null) {
+          typesAndDependencies
+              .addAll(findRawTypesWithInboundReferences(variable.defaultType));
+        }
+      }
+    }
+    if (type.formals != null) {
+      for (FormalParameterBuilder<TypeBuilder> formal in type.formals) {
+        typesAndDependencies
+            .addAll(findRawTypesWithInboundReferences(formal.type));
+      }
+    }
+  }
+  return typesAndDependencies;
+}
+
+/// Finds issues by raw generic types with inbound references in type variables.
+///
+/// Returns flattened list of triplets.  The first element of the triplet is the
+/// [TypeDeclarationBuilder] for the type variable from [variables] that has raw
+/// generic types with inbound references in its bound.  The second element of
+/// the triplet is the error message.  The third element is the context.
+List<Object> getInboundReferenceIssues(
+    List<TypeVariableBuilder<TypeBuilder, Object>> variables) {
+  var issues = <Object>[];
+  for (TypeVariableBuilder<TypeBuilder, Object> variable in variables) {
+    if (variable.bound != null) {
+      List<Object> rawTypesAndMutualDependencies =
+          findRawTypesWithInboundReferences(variable.bound);
+      for (int i = 0; i < rawTypesAndMutualDependencies.length; i += 2) {
+        NamedTypeBuilder<TypeBuilder, Object> type =
+            rawTypesAndMutualDependencies[i];
+        List<Object> variablesAndDependencies =
+            rawTypesAndMutualDependencies[i + 1];
+        for (int j = 0; j < variablesAndDependencies.length; j += 2) {
+          TypeVariableBuilder<TypeBuilder, Object> dependent =
+              variablesAndDependencies[j];
+          List<NamedTypeBuilder<TypeBuilder, Object>> dependencies =
+              variablesAndDependencies[j + 1];
+          for (NamedTypeBuilder<TypeBuilder, Object> dependency
+              in dependencies) {
+            issues.add(variable);
+            issues.add(templateBoundIssueViaRawTypeWithNonSimpleBounds
+                .withArguments(type.declaration.name));
+            issues.add(<LocatedMessage>[
+              templateNonSimpleBoundViaVariable
+                  .withArguments(dependency.declaration.name)
+                  .withLocation(dependent.fileUri, dependent.charOffset,
+                      dependent.name.length)
+            ]);
+          }
+        }
+        if (variablesAndDependencies.length == 0) {
+          // The inbound references are in a compiled declaration in a .dill.
+          issues.add(variable);
+          issues.add(templateBoundIssueViaRawTypeWithNonSimpleBounds
+              .withArguments(type.declaration.name));
+          issues.add(const <LocatedMessage>[]);
+        }
+      }
+    }
+  }
+  return issues;
+}
+
+/// Finds raw type paths starting from those in [start] and ending with [end].
+///
+/// Returns list of found paths.  Each path is represented as a list of
+/// alternating builders of the raw generic types from the path and builders of
+/// type variables of the immediately preceding types that contain the reference
+/// to the next raw generic type in the path.  The list ends with the type
+/// builder for [end].
+///
+/// The reason for putting the type variables into the paths as well as for
+/// using type for [start], and not the corresponding type declaration,
+/// is better error reporting.
+List<List<Object>> findRawTypePathsToDeclaration(
+    TypeBuilder start, TypeDeclarationBuilder<TypeBuilder, Object> end,
+    [Set<TypeDeclarationBuilder<TypeBuilder, Object>> visited]) {
+  visited ??= new Set<TypeDeclarationBuilder<TypeBuilder, Object>>.identity();
+  var paths = <List<Object>>[];
+  if (start is NamedTypeBuilder<TypeBuilder, Object>) {
+    TypeDeclarationBuilder<TypeBuilder, Object> declaration = start.declaration;
+    if (start.arguments == null) {
+      if (start.declaration == end) {
+        paths.add(<Object>[start]);
+      } else if (visited.add(start.declaration)) {
+        if (declaration is ClassBuilder<TypeBuilder, Object> &&
+            declaration.typeVariables != null) {
+          for (TypeVariableBuilder<TypeBuilder, Object> variable
+              in declaration.typeVariables) {
+            if (variable.bound != null) {
+              for (List<Object> path in findRawTypePathsToDeclaration(
+                  variable.bound, end, visited)) {
+                paths.add(<Object>[start, variable]..addAll(path));
+              }
+            }
+          }
+        } else if (declaration
+                is FunctionTypeAliasBuilder<TypeBuilder, Object> &&
+            declaration.typeVariables != null) {
+          for (TypeVariableBuilder<TypeBuilder, Object> variable
+              in declaration.typeVariables) {
+            if (variable.bound != null) {
+              for (List<Object> dependencyPath in findRawTypePathsToDeclaration(
+                  variable.bound, end, visited)) {
+                paths.add(<Object>[start, variable]..addAll(dependencyPath));
+              }
+            }
+          }
+        }
+        visited.remove(start.declaration);
+      }
+    } else {
+      for (TypeBuilder argument in start.arguments) {
+        paths.addAll(findRawTypePathsToDeclaration(argument, end, visited));
+      }
+    }
+  } else if (start is FunctionTypeBuilder) {
+    paths.addAll(findRawTypePathsToDeclaration(start.returnType, end, visited));
+    if (start.typeVariables != null) {
+      for (TypeVariableBuilder<TypeBuilder, Object> variable
+          in start.typeVariables) {
+        if (variable.bound != null) {
+          paths.addAll(
+              findRawTypePathsToDeclaration(variable.bound, end, visited));
+        }
+        if (variable.defaultType != null) {
+          paths.addAll(findRawTypePathsToDeclaration(
+              variable.defaultType, end, visited));
+        }
+      }
+    }
+    if (start.formals != null) {
+      for (FormalParameterBuilder<TypeBuilder> formal in start.formals) {
+        paths.addAll(findRawTypePathsToDeclaration(formal.type, end, visited));
+      }
+    }
+  }
+  return paths;
+}
+
+/// Finds raw generic type cycles ending and starting with [declaration].
+///
+/// Returns list of found cycles.  Each cycle is represented as a list of
+/// alternating raw generic types from the cycle and type variables of the
+/// immediately preceding type that reference the next type in the cycle.  The
+/// cycle starts with a type variable from [declaration] and ends with a type
+/// that has [declaration] as its declaration.
+///
+/// The reason for putting the type variables into the cycles is better error
+/// reporting.
+List<List<Object>> findRawTypeCycles(
+    TypeDeclarationBuilder<TypeBuilder, Object> declaration) {
+  var cycles = <List<Object>>[];
+  if (declaration is ClassBuilder<TypeBuilder, Object> &&
+      declaration.typeVariables != null) {
+    for (TypeVariableBuilder<TypeBuilder, Object> variable
+        in declaration.typeVariables) {
+      if (variable.bound != null) {
+        for (List<Object> path
+            in findRawTypePathsToDeclaration(variable.bound, declaration)) {
+          cycles.add(<Object>[variable]..addAll(path));
+        }
+      }
+    }
+  } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object> &&
+      declaration.typeVariables != null) {
+    for (TypeVariableBuilder<TypeBuilder, Object> variable
+        in declaration.typeVariables) {
+      if (variable.bound != null) {
+        for (List<Object> dependencyPath
+            in findRawTypePathsToDeclaration(variable.bound, declaration)) {
+          cycles.add(<Object>[variable]..addAll(dependencyPath));
+        }
+      }
+    }
+  }
+  return cycles;
+}
+
+/// Converts raw generic type [cycles] for [declaration] into reportable issues.
+///
+/// The [cycles] are expected to be in the format specified for the return value
+/// of [findRawTypeCycles].
+///
+/// Returns flattened list of triplets.  The first element of the triplet is the
+/// [TypeDeclarationBuilder] for the type variable from [variables] that has raw
+/// generic types with inbound references in its bound.  The second element of
+/// the triplet is the error message.  The third element is the context.
+List<Object> convertRawTypeCyclesIntoIssues(
+    TypeDeclarationBuilder<TypeBuilder, Object> declaration,
+    List<List<Object>> cycles) {
+  List<Object> issues = <Object>[];
+  for (List<Object> cycle in cycles) {
+    if (cycle.length == 2) {
+      // Loop.
+      TypeVariableBuilder<TypeBuilder, Object> variable = cycle[0];
+      NamedTypeBuilder<TypeBuilder, Object> type = cycle[1];
+      issues.add(variable);
+      issues.add(templateBoundIssueViaLoopNonSimplicity
+          .withArguments(type.declaration.name));
+      issues.add(null); // Context.
+    } else {
+      var context = <LocatedMessage>[];
+      for (int i = 0; i < cycle.length; i += 2) {
+        TypeVariableBuilder<TypeBuilder, Object> variable = cycle[i];
+        NamedTypeBuilder<TypeBuilder, Object> type = cycle[i + 1];
+        context.add(templateNonSimpleBoundViaReference
+            .withArguments(type.declaration.name)
+            .withLocation(
+                variable.fileUri, variable.charOffset, variable.name.length));
+      }
+      NamedTypeBuilder<TypeBuilder, Object> firstEncounteredType = cycle[1];
+
+      issues.add(declaration);
+      issues.add(templateBoundIssueViaCycleNonSimplicity.withArguments(
+          declaration.name, firstEncounteredType.declaration.name));
+      issues.add(context);
+    }
+  }
+  return issues;
+}
+
+/// Finds issues by cycles of raw generic types containing [declaration].
+///
+/// Returns flattened list of triplets according to the format specified by
+/// [convertRawTypeCyclesIntoIssues].
+List<Object> getRawTypeCycleIssues(
+    TypeDeclarationBuilder<TypeBuilder, Object> declaration) {
+  return convertRawTypeCyclesIntoIssues(
+      declaration, findRawTypeCycles(declaration));
+}
+
+/// Finds non-simplicity issues for the given set of [variables].
+///
+/// The issues are those caused by raw types with inbound references in the
+/// bounds of their type variables.
+///
+/// Returns flattened list of triplets, each triplet representing an issue.  The
+/// first element in the triplet is the type declaration that has the issue.
+/// The second element in the triplet is the error message.  The third element
+/// in the triplet is the context.
+List<Object> getNonSimplicityIssuesForTypeVariables(
+    List<TypeVariableBuilder<TypeBuilder, Object>> variables) {
+  if (variables == null) return <Object>[];
+  return getInboundReferenceIssues(variables);
+}
+
+/// Finds non-simplicity issues for the given [declaration].
+///
+/// The issues are those caused by raw types with inbound references in the
+/// bounds of type variables from [declaration] and by cycles of raw types
+/// containing [declaration].
+///
+/// Returns flattened list of triplets, each triplet representing an issue.  The
+/// first element in the triplet is the type declaration that has the issue.
+/// The second element in the triplet is the error message.  The third element
+/// in the triplet is the context.
+List<Object> getNonSimplicityIssuesForDeclaration(
+    TypeDeclarationBuilder<TypeBuilder, Object> declaration) {
+  var issues = <Object>[];
+  if (declaration is ClassBuilder<TypeBuilder, Object> &&
+      declaration.typeVariables != null) {
+    issues.addAll(getInboundReferenceIssues(declaration.typeVariables));
+  } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object> &&
+      declaration.typeVariables != null) {
+    issues.addAll(getInboundReferenceIssues(declaration.typeVariables));
+  }
+  List<List<Object>> cyclesToReport = <List<Object>>[];
+  for (List<Object> cycle in findRawTypeCycles(declaration)) {
+    // To avoid reporting the same error for each element of the cycle, we only
+    // do so if it comes the first in the lexicographical order.  Note that
+    // one-element cycles shouldn't be checked, as they are loops.
+    if (cycle.length == 2) {
+      cyclesToReport.add(cycle);
+    } else {
+      String declarationPathAndName =
+          "${declaration.fileUri}:${declaration.name}";
+      String lexMinPathAndName = null;
+      for (int i = 1; i < cycle.length; i += 2) {
+        NamedTypeBuilder<TypeBuilder, Object> type = cycle[i];
+        String pathAndName =
+            "${type.declaration.fileUri}:${type.declaration.name}";
+        if (lexMinPathAndName == null ||
+            lexMinPathAndName.compareTo(pathAndName) > 0) {
+          lexMinPathAndName = pathAndName;
+        }
+      }
+      if (declarationPathAndName == lexMinPathAndName) {
+        cyclesToReport.add(cycle);
+      }
+    }
+  }
+  issues.addAll(convertRawTypeCyclesIntoIssues(declaration, cyclesToReport));
+  return issues;
+}
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 80657f8..637cba2 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -2338,3 +2338,40 @@
   tip: "Try changing the literal to something that can be represented in Javascript. In Javascript #string2 is the nearest value that can be represented exactly."
   severity: ERROR
   dart2jsCode: "*fatal*"
+
+BoundIssueViaRawTypeWithNonSimpleBounds:
+  template: "Generic type '#name' can't be used without type arguments in a type variable bound."
+  tip: "Try providing type arguments to '#name' here."
+  severity: ERROR
+  analyzerCode: STRONG_MODE_NOT_INSTANTIATED_BOUND
+  dart2jsCode: "*fatal*"
+  script: >
+    class Hest<X extends Hest<X>> {}
+    class Fisk<Y extends Hest> {}
+
+NonSimpleBoundViaVariable:
+  template: "Bound of this variable references variable '#name' from the same declaration."
+  severity: CONTEXT
+
+BoundIssueViaLoopNonSimplicity:
+  template: "Generic type '#name' can't be used without type arguments in the bounds of its own type variables."
+  tip: "Try providing type arguments to '#name' here."
+  severity: ERROR
+  analyzerCode: STRONG_MODE_NOT_INSTANTIATED_BOUND
+  dart2jsCode: "*fatal*"
+  script: >
+    class Hest<X extends Hest> {}
+
+BoundIssueViaCycleNonSimplicity:
+  template: "Generic type '#name' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '#name2'."
+  tip: "Try providing type arguments to '#name2' here or to some other raw types in the bounds along the reference chain."
+  severity: ERROR
+  analyzerCode: STRONG_MODE_NOT_INSTANTIATED_BOUND
+  dart2jsCode: "*fatal*"
+  script: >
+    class Hest<X extends Fisk> {}
+    class Fisk<Y extends Hest> {}
+
+NonSimpleBoundViaReference:
+  template: "Bound of this variable references raw type '#name'."
+  severity: CONTEXT
diff --git a/pkg/front_end/testcases/compile.status b/pkg/front_end/testcases/compile.status
index 1623e1d..0314972 100644
--- a/pkg/front_end/testcases/compile.status
+++ b/pkg/front_end/testcases/compile.status
@@ -45,6 +45,23 @@
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: Fail
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: Fail
 
+instantiate_to_bound/non_simple_bound_due_to_non_simple: Fail
+instantiate_to_bound/non_simple_bound_due_to_variables: Fail
+instantiate_to_bound/non_simple_co_inductive: Fail
+instantiate_to_bound/non_simple_co_inductive_for_each: Fail
+instantiate_to_bound/non_simple_co_inductive_no_dup: Fail
+instantiate_to_bound/non_simple_folded_regress: Fail
+instantiate_to_bound/non_simple_for_each: Fail
+instantiate_to_bound/non_simple_generic_function_in_bound_regress: Fail
+instantiate_to_bound/non_simple_many: Fail
+instantiate_to_bound/non_simple_no_dup: Fail
+instantiate_to_bound/non_simple_suppress_consequence: Fail
+instantiate_to_bound/non_simple_variables_from_same: Fail
+instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: Fail
+instantiate_to_bound/non_simple_class_typedef_cycle: Fail
+instantiate_to_bound/non_simple_from_compiled: Fail
+instantiate_to_bound/non_simple_many_libs_same_name_cycle: Fail
+
 rasta/abstract_constructor: Fail
 rasta/bad_constructor_redirection: Fail
 rasta/bad_continue: Fail
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart
new file mode 100644
index 0000000..b63fbe0
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_non_simple.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a compile-time error is generated when instantaite to
+// bound can't be applied due to raw types with non-simple bounds.  The
+// non-simplicity in this test is due to having another raw type in the bound
+// that in its turn has type variables with non-simple bounds.
+
+class A<TypeT, TypeS extends TypeT> {}
+
+class B<TypeU extends A> {}
+
+class C<TypeV extends B> {}
+
+C c;
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart
new file mode 100644
index 0000000..6d25acd
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_bound_due_to_variables.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a compile-time error is generated when instantiate to
+// bound can't be applied due to raw types with non-simple bounds.  The
+// non-simplicity in this test is due to dependencies between type variables.
+
+class A<TypeT, TypeS extends TypeT> {}
+
+class B<TypeU extends A> {}
+
+B b;
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart
new file mode 100644
index 0000000..d3acace
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_parametrized_typedef_cycle.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the cyclic non-simplicity issues are detected in case
+// when both class declaration and a parametrized typedef participate in the
+// cycle.
+
+class Hest<TypeX extends Fisk> {}
+
+typedef Fisk = void Function<TypeY extends Hest>();
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart
new file mode 100644
index 0000000..5aebdc0
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the cyclic non-simplicity detection works in case when
+// both class declarations and typedefs participate in the cycle.
+
+class Hest<TypeX extends Fisk> {}
+
+typedef void Fisk<TypeY extends Hest>();
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart
new file mode 100644
index 0000000..5df69f7
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the use of a raw generic type in the bounds of its own
+// type variables is recognized and reported as a compile-time error.
+
+class Hest<TypeX extends Hest> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart
new file mode 100644
index 0000000..2703630
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_for_each.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the error is reported for all type variables that
+// reference the raw generic type they are defined on.
+
+class Hest<TypeX extends Hest, TypeY extends Hest> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart
new file mode 100644
index 0000000..a72f472
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_co_inductive_no_dup.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the error message is not duplicated in case when the
+// raw generic type is used more than once in the bound of its own type
+// variable.
+
+class Hest<TypeX extends Map<Hest, Hest>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart
new file mode 100644
index 0000000..91a3b2b
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_folded_regress.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that same generic type passed as a type argument to itself
+// doesn't cause issues in the mechanism for detection of non-simple bounds.
+
+class Hest<TypeX> {}
+
+class Fisk<TypeY extends Hest<Hest<Object>>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart
new file mode 100644
index 0000000..e7415fe
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_for_each.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that an error is reported on all type variables that have a
+// raw generic type in their bounds in case this generic type has non-simple
+// bounds.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Hest, TypeZ extends Hest> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart
new file mode 100644
index 0000000..696a47f
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the use of a raw generic type with non-simple bounds in
+// a bound of a type variable is detected when that generic type comes from a
+// compiled .dill file.
+//
+// Note that the type variable of LinkedListEntry has non-simple bound because
+// it references itself.
+// https://api.dartlang.org/stable/1.24.3/dart-collection/LinkedListEntry-class.html
+
+import 'dart:collection';
+
+class Hest<X extends LinkedListEntry> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart
new file mode 100644
index 0000000..18d2e53
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_generic_function_in_bound_regress.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the use of generic function types in the bound of a
+// type variable is detected early and doesn't cause issues to the mechanism for
+// detection of non-simple bounds.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Function<TypeZ extends Hest<Null>>(TypeZ)> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart
new file mode 100644
index 0000000..496b166
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that an error is reported on all raw generic types with
+// non-simple bounds used in the bound of the same type variable.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Fisk<TypeY>> {}
+
+class Naebdyr<TypeZ extends Map<Hest, Fisk>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart
new file mode 100644
index 0000000..e2c8f9c
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a cyclic dependence is not reported twice in case the
+// class declarations from the cycle are in different libraries, but have the
+// same name within their respective libraries.
+
+import './non_simple_many_libs_same_name_cycle_lib.dart' as lib;
+
+class Hest<TypeX extends lib.Hest> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle_lib.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle_lib.dart
new file mode 100644
index 0000000..a716476
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_many_libs_same_name_cycle_lib.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a cyclic dependence is not reported twice in case the
+// class declarations from the cycle are in different libraries, but have the
+// same name within their respective libraries.
+//
+// This file is the supplement library for
+// 'non_simple_many_libs_same_name_cycle.dart'.
+
+library non_simple_many_libs_same_name_cycle_lib;
+
+import './non_simple_many_libs_same_name_cycle.dart' as lib;
+
+class Hest<TypeY extends lib.Hest> {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart
new file mode 100644
index 0000000..dbedd5a
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_no_dup.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the error message is not duplicated in the case when
+// the same raw generic type with non-simple bounds is used in the bound of a
+// type variable.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Map<Hest, Hest>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart
new file mode 100644
index 0000000..9e41974
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_suppress_consequence.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that in the case of an error on a class related to
+// non-simple bounds, the implied errors on other classes that reference the
+// erronious one in the bounds of their type variables is not reported.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Hest> {}
+
+class Naebdyr<TypeZ extends Fisk> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart b/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart
new file mode 100644
index 0000000..8dc56a0
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_variables_from_same.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that an attempt to use a raw generic type with non-simple
+// bounds is detected and reported as a compile-time error in case the
+// non-simple bound is due to the use of the type variable from the same
+// declaration.
+
+class Hest<TypeX extends Hest<TypeX>> {}
+
+class Fisk<TypeY extends Hest> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 9cdafa9..80c77ad 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -247,6 +247,23 @@
 inference/unsafe_block_closure_inference_method_call_no_type_param: Fail
 inference/void_return_type_subtypes_dynamic: Fail
 
+instantiate_to_bound/non_simple_bound_due_to_non_simple: Fail
+instantiate_to_bound/non_simple_bound_due_to_variables: Fail
+instantiate_to_bound/non_simple_co_inductive: Fail
+instantiate_to_bound/non_simple_co_inductive_for_each: Fail
+instantiate_to_bound/non_simple_co_inductive_no_dup: Fail
+instantiate_to_bound/non_simple_folded_regress: Fail
+instantiate_to_bound/non_simple_for_each: Fail
+instantiate_to_bound/non_simple_generic_function_in_bound_regress: Fail
+instantiate_to_bound/non_simple_many: Fail
+instantiate_to_bound/non_simple_no_dup: Fail
+instantiate_to_bound/non_simple_suppress_consequence: Fail
+instantiate_to_bound/non_simple_variables_from_same: Fail
+instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: Fail
+instantiate_to_bound/non_simple_class_typedef_cycle: Fail
+instantiate_to_bound/non_simple_from_compiled: Fail
+instantiate_to_bound/non_simple_many_libs_same_name_cycle: Fail
+
 rasta/issue_000045: Fail
 rasta/issue_000046: Fail
 rasta/issue_000047: Fail
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index b0858b9..805d397 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -112,8 +112,24 @@
 inference_new/infer_field_getter_setter_mismatch: TypeCheckError
 inference_new/infer_field_override_getter_overrides_setter: TypeCheckError
 
-instantiate_to_bound/typedef_super_bounded_type: Fail
 instantiate_to_bound/body_typedef_super_bounded_type: Fail
+instantiate_to_bound/non_simple_bound_due_to_non_simple: Fail
+instantiate_to_bound/non_simple_bound_due_to_variables: Fail
+instantiate_to_bound/non_simple_co_inductive: Fail
+instantiate_to_bound/non_simple_co_inductive_for_each: Fail
+instantiate_to_bound/non_simple_co_inductive_no_dup: Fail
+instantiate_to_bound/non_simple_folded_regress: Fail
+instantiate_to_bound/non_simple_for_each: Fail
+instantiate_to_bound/non_simple_generic_function_in_bound_regress: Fail
+instantiate_to_bound/non_simple_many: Fail
+instantiate_to_bound/non_simple_no_dup: Fail
+instantiate_to_bound/non_simple_suppress_consequence: Fail
+instantiate_to_bound/non_simple_variables_from_same: Fail
+instantiate_to_bound/typedef_super_bounded_type: Fail
+instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: Crash # Issue 33479
+instantiate_to_bound/non_simple_class_typedef_cycle: Fail
+instantiate_to_bound/non_simple_from_compiled: Fail
+instantiate_to_bound/non_simple_many_libs_same_name_cycle: Fail
 
 rasta/abstract_constructor: Fail
 rasta/bad_constructor_redirection: Fail
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 4f64cd4..7eabb3c 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -73,6 +73,8 @@
 Language/Expressions/Constants/no_other_constant_expressions_t11: MissingCompileTimeError
 Language/Expressions/Constants/ternary_operator_t02: MissingCompileTimeError
 Language/Expressions/Instance_Creation/Const/exception_t01: MissingCompileTimeError
+Language/Generics/syntax_t02: CompileTimeError
+Language/Generics/syntax_t03: CompileTimeError
 Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_members_t01: CompileTimeError
 Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_method_and_getter_t01: CompileTimeError
 Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_method_and_getter_t02: CompileTimeError
@@ -1107,8 +1109,6 @@
 Language/Types/Static_Types/malformed_type_t04: CompileTimeError
 Language/Types/Static_Types/malformed_type_t05: CompileTimeError
 Language/Types/Static_Types/malformed_type_t06: CompileTimeError
-Language/Types/Type_Declarations/Typedef/self_reference_t08: Crash
-Language/Types/Type_Declarations/Typedef/self_reference_t09: Crash
 Language/Types/Type_Declarations/Typedef/syntax_t01: CompileTimeError
 Language/Types/Type_Void/syntax_t08: MissingCompileTimeError
 Language/Types/Type_Void/syntax_t09: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 8d8804b..f45f4da 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -577,8 +577,6 @@
 cyclic_type_test/02: RuntimeError
 cyclic_type_test/03: RuntimeError
 cyclic_type_test/04: RuntimeError
-cyclic_typedef_test/10: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/out/ReleaseX64/generated_tests/language_2/cyclic_typedef_test_10.dart,
-cyclic_typedef_test/11: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/out/ReleaseX64/generated_tests/language_2/cyclic_typedef_test_11.dart,
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError
 deferred_inheritance_constraints_test/implements: MissingCompileTimeError
 deferred_inheritance_constraints_test/mixin: MissingCompileTimeError
@@ -772,7 +770,6 @@
 redirecting_factory_default_values_test/01: MissingCompileTimeError
 redirecting_factory_default_values_test/02: MissingCompileTimeError
 redirecting_factory_reflection_test: RuntimeError
-regress_23089_test: Crash # Crash when compiling file:///usr/local/google/home/sra/Dart/sdk/tests/language_2/regress_23089_test.dart,
 regress_23408_test: CompileTimeError
 regress_24283_test: RuntimeError # non JS number semantics
 regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -965,8 +962,6 @@
 cyclic_type_variable_test/02: MissingCompileTimeError
 cyclic_type_variable_test/03: MissingCompileTimeError
 cyclic_type_variable_test/04: MissingCompileTimeError
-cyclic_typedef_test/10: Crash # Stack Overflow
-cyclic_typedef_test/11: Crash # Stack Overflow
 default_factory2_test/01: MissingCompileTimeError
 default_factory_test/01: MissingCompileTimeError
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError
@@ -1245,7 +1240,6 @@
 redirecting_factory_reflection_test: RuntimeError
 regress_13462_1_test: RuntimeError
 regress_18535_test: RuntimeError
-regress_23089_test: Crash # Stack Overflow
 regress_23408_test: CompileTimeError
 regress_24283_test: RuntimeError # non JS number semantics
 regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -1464,8 +1458,6 @@
 cyclic_type_variable_test/02: MissingCompileTimeError
 cyclic_type_variable_test/03: MissingCompileTimeError
 cyclic_type_variable_test/04: MissingCompileTimeError
-cyclic_typedef_test/10: Crash # Stack Overflow
-cyclic_typedef_test/11: Crash # Stack Overflow
 default_factory2_test/01: MissingCompileTimeError
 default_factory_test/01: MissingCompileTimeError
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError
@@ -1749,7 +1741,6 @@
 regress_13462_1_test: RuntimeError
 regress_18535_test: RuntimeError
 regress_21795_test: RuntimeError # Issue 12605
-regress_23089_test: Crash # Stack Overflow
 regress_23408_test: CompileTimeError
 regress_24283_test: RuntimeError, OK # Requires 64 bit numbers.
 regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index e8e6bc4..1cbbedc 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -349,8 +349,6 @@
 cyclic_type_variable_test/02: MissingCompileTimeError
 cyclic_type_variable_test/03: MissingCompileTimeError
 cyclic_type_variable_test/04: MissingCompileTimeError
-cyclic_typedef_test/10: Crash
-cyclic_typedef_test/11: Crash
 default_factory2_test/01: MissingCompileTimeError
 default_factory_test/01: MissingCompileTimeError
 deferred_inheritance_constraints_test/extends: MissingCompileTimeError
@@ -550,7 +548,6 @@
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
 redirecting_factory_malbounded_test/01: MissingCompileTimeError
 redirecting_factory_reflection_test: RuntimeError # UnimplementedError: node <InvalidExpression> `invalid-expression`
-regress_23089_test: Crash # Crashes in KernelClassBuilder.buildTypeArguments
 regress_23408_test: CompileTimeError # Issue 31533
 regress_24283_test: RuntimeError # Expect.equals(expected: <-1>, actual: <4294967295>) fails.
 regress_29025_test: CompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 8c36894..18a73da 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -48,8 +48,6 @@
 cyclic_type2_test: CompileTimeError
 cyclic_type_test/02: CompileTimeError
 cyclic_type_test/04: CompileTimeError
-cyclic_typedef_test/10: DartkCrash
-cyclic_typedef_test/11: DartkCrash
 deferred_call_empty_before_load_test: RuntimeError
 deferred_load_constants_test/none: RuntimeError
 deferred_not_loaded_check_test: RuntimeError
@@ -141,7 +139,6 @@
 override_inheritance_method_test/29: CompileTimeError
 parser_quirks_test: CompileTimeError
 regress_22443_test: RuntimeError
-regress_23089_test: DartkCrash
 regress_23408_test: CompileTimeError
 regress_29025_test: CompileTimeError
 regress_29405_test: CompileTimeError
@@ -740,8 +737,6 @@
 cyclic_type2_test: RuntimeError, CompileTimeError
 cyclic_type_test/02: RuntimeError, CompileTimeError
 cyclic_type_test/04: RuntimeError, CompileTimeError
-cyclic_typedef_test/10: Crash # Issue 32416.
-cyclic_typedef_test/11: Crash # Issue 32416.
 deferred_call_empty_before_load_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
 deferred_load_constants_test/none: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
 deferred_load_library_wrong_args_test/01: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 30273.
@@ -817,7 +812,6 @@
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
 redirecting_factory_malbounded_test/01: MissingCompileTimeError
 regress_22443_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
-regress_23089_test: Crash # Issue 32417.
 regress_23408_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 30273.
 regress_23408_test: RuntimeError
 regress_29025_test: CompileTimeError # Issue 31402 (Variable declaration)
@@ -1037,8 +1031,6 @@
 cyclic_type2_test: Fail, OK
 cyclic_type_test/02: Fail, OK # Non-contractive types are not supported in the vm.
 cyclic_type_test/04: Fail, OK
-cyclic_typedef_test/10: Crash # Issue 32416.
-cyclic_typedef_test/11: Crash # Issue 32416.
 deferred_call_empty_before_load_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 deferred_load_constants_test/none: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
 deferred_load_library_wrong_args_test/01: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 30273.
@@ -1167,7 +1159,6 @@
 regress_13462_1_test: SkipByDesign
 regress_18535_test: SkipByDesign
 regress_22443_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
-regress_23089_test: Crash # Issue 32417.
 regress_23408_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 30273.
 regress_23408_test: RuntimeError
 regress_28255_test: SkipByDesign
@@ -1280,8 +1271,6 @@
 config_import_test: Crash
 const_constructor3_test/04: MissingCompileTimeError
 constants_test/05: MissingCompileTimeError
-cyclic_typedef_test/10: Crash
-cyclic_typedef_test/11: Crash
 deferred_load_library_wrong_args_test/01: CompileTimeError
 duplicate_implements_test/01: MissingCompileTimeError
 duplicate_implements_test/02: MissingCompileTimeError
@@ -1364,7 +1353,6 @@
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
 parser_quirks_test: CompileTimeError
-regress_23089_test: Crash
 regress_23408_test: CompileTimeError
 regress_29025_test: CompileTimeError
 regress_29405_test: CompileTimeError
@@ -1442,6 +1430,7 @@
 prefix_transitive_import_prefix_test/03: MissingCompileTimeError
 prefix_transitive_import_test/01: MissingCompileTimeError
 prefix_transitive_import_test/02: MissingCompileTimeError
+regress_23089_test: MissingCompileTimeError
 setter_override2_test/02: MissingCompileTimeError
 super_no_such_method4_test/01: MissingCompileTimeError # Requires Dart 2 semantics. See http://dartbug.com/33380.
 super_no_such_method5_test/01: MissingCompileTimeError # Requires Dart 2 semantics. See http://dartbug.com/33380.
@@ -2077,7 +2066,6 @@
 regress_21912_test/02: MissingCompileTimeError
 regress_22438_test: MissingCompileTimeError
 regress_22936_test: MissingCompileTimeError
-regress_23089_test: MissingCompileTimeError
 regress_26133_test: MissingCompileTimeError
 regress_27572_test: MissingCompileTimeError
 regress_28217_test/01: MissingCompileTimeError