From 2c6eabd3c468e1f254f5a6f0db012b561d394938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20von=20der=20Ahe=CC=81?= Date: Mon, 22 Oct 2018 12:41:59 +0000 Subject: [PATCH] Compute substitution map on kernel objects instead of builders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/dart-lang/sdk/issues/34856 Change-Id: I150a390ea19e684e7951c1354c09fd40845e4328 Reviewed-on: https://dart-review.googlesource.com/c/81006 Reviewed-by: Kevin Millikin Commit-Queue: Peter von der Ahé --- .../lib/src/fasta/fasta_codes_generated.dart | 24 ---- .../fasta/kernel/kernel_class_builder.dart | 98 ++++------------ .../lib/src/fasta/kernel/kernel_target.dart | 3 +- pkg/front_end/messages.yaml | 4 - pkg/front_end/test/issue_34856_test.dart | 108 ++++++++++++++++++ 5 files changed, 134 insertions(+), 103 deletions(-) create mode 100644 pkg/front_end/test/issue_34856_test.dart 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 706a85dd50ef9..6769e5c928a09 100644 --- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart +++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart @@ -4934,30 +4934,6 @@ Message _withArgumentsInternalProblemStoringMultipleInferredTypes( arguments: {'type': _type, 'name': name}); } -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Template - templateInternalProblemSuperclassNotFound = - const Template( - messageTemplate: r"""Superclass not found '#name'.""", - withArguments: _withArgumentsInternalProblemSuperclassNotFound); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Code - codeInternalProblemSuperclassNotFound = - const Code( - "InternalProblemSuperclassNotFound", - templateInternalProblemSuperclassNotFound, - severity: Severity.internalProblem); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -Message _withArgumentsInternalProblemSuperclassNotFound(String name) { - if (name.isEmpty) throw 'No name provided'; - name = demangleMixinApplicationName(name); - return new Message(codeInternalProblemSuperclassNotFound, - message: """Superclass not found '${name}'.""", - arguments: {'name': name}); -} - // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. const Template templateInternalProblemUnexpected = diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart index b913847b0688b..56bc3b2cc04c8 100644 --- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart @@ -41,7 +41,7 @@ import 'package:kernel/clone.dart' show CloneWithoutBody; import 'package:kernel/core_types.dart' show CoreTypes; -import 'package:kernel/type_algebra.dart' show Substitution; +import 'package:kernel/type_algebra.dart' show Substitution, substitute; import 'package:kernel/type_algebra.dart' as type_algebra show getSubstitutionMap; @@ -73,7 +73,6 @@ import '../fasta_codes.dart' templateIncorrectTypeArgumentInSupertype, templateIncorrectTypeArgumentInSupertypeInferred, templateInterfaceCheckContext, - templateInternalProblemSuperclassNotFound, templateMissingImplementationCause, templateMissingImplementationNotAbstract, templateMixinApplicationIncompatibleSupertype, @@ -96,8 +95,7 @@ import '../fasta_codes.dart' import '../names.dart' show noSuchMethodName; -import '../problems.dart' - show internalProblem, unexpected, unhandled, unimplemented; +import '../problems.dart' show unexpected, unhandled, unimplemented; import '../type_inference/type_schema.dart' show UnknownType; @@ -116,11 +114,8 @@ import 'kernel_builder.dart' LibraryBuilder, MemberBuilder, MetadataBuilder, - MixinApplicationBuilder, - NamedTypeBuilder, ProcedureBuilder, Scope, - TypeBuilder, TypeVariableBuilder; import 'redirecting_factory_body.dart' @@ -1741,66 +1736,30 @@ abstract class KernelClassBuilder /// /// [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}. /// - /// This method returns null if the map is empty, and it's an error if - /// [superclass] isn't a superclass. - Map getSubstitutionMap(ClassBuilder superclass, - Uri fileUri, int charOffset, TypeBuilder dynamicType) { - TypeBuilder supertype = this.supertype; - Map substitutionMap; - List arguments; - List variables; - Declaration declaration; - - /// If [application] is mixing in [superclass] directly or via other named - /// mixin applications, return it. - NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) { - for (TypeBuilder t in application.mixins) { - if (t is NamedTypeBuilder) { - if (t.declaration == superclass) return t; - } else if (t is MixinApplicationBuilder) { - NamedTypeBuilder s = findSuperclass(t); - if (s != null) return s; - } - } - return null; - } - - void handleNamedTypeBuilder(NamedTypeBuilder t) { - declaration = t.declaration; - arguments = t.arguments ?? const []; - if (declaration is ClassBuilder) { - ClassBuilder cls = declaration; - variables = cls.typeVariables; - supertype = cls.supertype; - } - } - - while (declaration != superclass) { - variables = null; - if (supertype is NamedTypeBuilder) { - handleNamedTypeBuilder(supertype); - } else if (supertype is MixinApplicationBuilder) { - MixinApplicationBuilder t = supertype; - NamedTypeBuilder s = findSuperclass(t); - if (s != null) { - handleNamedTypeBuilder(s); - } - supertype = t.supertype; - } else { - internalProblem( - templateInternalProblemSuperclassNotFound - .withArguments(superclass.fullNameForErrors), - charOffset, - fileUri); - } - if (variables != null) { - Map directSubstitutionMap = - {}; + /// It's an error if [superclass] isn't a superclass. + Map getSubstitutionMap(Class superclass) { + Supertype supertype = target.supertype; + Map substitutionMap = {}; + List arguments; + List variables; + Class classNode; + + while (classNode != superclass) { + classNode = supertype.classNode; + arguments = supertype.typeArguments; + variables = classNode.typeParameters; + supertype = classNode.supertype; + if (variables.isNotEmpty) { + Map directSubstitutionMap = + {}; for (int i = 0; i < variables.length; i++) { - TypeBuilder argument = - i < arguments.length ? arguments[i] : dynamicType; + DartType argument = + i < arguments.length ? arguments[i] : const DynamicType(); if (substitutionMap != null) { - argument = argument.subst(substitutionMap); + // TODO(ahe): Investigate if requiring the caller to use + // `substituteDeep` from `package:kernel/type_algebra.dart` instead + // of `substitute` is faster. If so, we can simply this code. + argument = substitute(argument, substitutionMap); } directSubstitutionMap[variables[i]] = argument; } @@ -1808,13 +1767,6 @@ abstract class KernelClassBuilder } } - if (substitutionMap == null) return const {}; - - Map result = {}; - substitutionMap - .forEach((TypeVariableBuilder variable, TypeBuilder argument) { - result[variable.target] = argument.build(library); - }); - return result; + return substitutionMap; } } diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart index fd807fce0a0b3..8354ddb30fc15 100644 --- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart @@ -481,8 +481,7 @@ class KernelTarget extends TargetImplementation { builder.addSyntheticConstructor(makeDefaultConstructor(builder.target)); } else { Map substitutionMap = - builder.getSubstitutionMap( - supertype, builder.fileUri, builder.charOffset, dynamicType); + builder.getSubstitutionMap(supertype.target); for (Constructor constructor in supertype.cls.constructors) { builder.addSyntheticConstructor(makeMixinApplicationConstructor( builder.target, builder.cls.mixin, constructor, substitutionMap)); diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index 5d3e0cf255c5d..60bb4557c1ac9 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -1576,10 +1576,6 @@ InternalProblemUnsupported: template: "Unsupported operation: '#name'." severity: INTERNAL_PROBLEM -InternalProblemSuperclassNotFound: - template: "Superclass not found '#name'." - severity: INTERNAL_PROBLEM - InternalProblemNotFound: template: "Couldn't find '#name'." severity: INTERNAL_PROBLEM diff --git a/pkg/front_end/test/issue_34856_test.dart b/pkg/front_end/test/issue_34856_test.dart new file mode 100644 index 0000000000000..c3f66935c575d --- /dev/null +++ b/pkg/front_end/test/issue_34856_test.dart @@ -0,0 +1,108 @@ +// 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. + +import 'dart:io' show File; + +import 'package:async_helper/async_helper.dart' show asyncTest; + +import 'package:front_end/src/api_prototype/compiler_options.dart' + show CompilerOptions; + +import 'package:front_end/src/api_prototype/kernel_generator.dart' + show kernelForComponent; + +import 'package:front_end/src/api_prototype/memory_file_system.dart' + show MemoryFileSystem; + +import 'package:front_end/src/base/processed_options.dart' + show ProcessedOptions; + +import 'package:front_end/src/compute_platform_binaries_location.dart' + show computePlatformBinariesLocation; + +import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext; + +import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent; + +import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent; + +import 'package:kernel/ast.dart' show Component; + +const Map files = const { + "repro.dart": """ + +import 'lib.dart'; + +abstract class M implements Map> {} + +abstract class C extends UnmodifiableMapView> + with M { + C._() : super(null); +} +""", + "lib.dart": """abstract class MapView { + const MapView(Map map); +} + +abstract class _UnmodifiableMapMixin {} + +abstract class UnmodifiableMapView extends MapView + with _UnmodifiableMapMixin { + UnmodifiableMapView(Map map) : super(map); +}""", +}; + +Future test() async { + final String platformBaseName = "vm_platform_strong.dill"; + final Uri base = Uri.parse("org-dartlang-test:///"); + final Uri platformDill = base.resolve(platformBaseName); + final List platformDillBytes = await new File.fromUri( + computePlatformBinariesLocation(forceBuildDir: true) + .resolve(platformBaseName)) + .readAsBytes(); + MemoryFileSystem fs = new MemoryFileSystem(base); + fs.entityForUri(platformDill).writeAsBytesSync(platformDillBytes); + fs + .entityForUri(base.resolve("lib.dart")) + .writeAsStringSync(files["lib.dart"]); + CompilerOptions options = new CompilerOptions() + ..fileSystem = fs + ..sdkSummary = platformDill; + + Component component = + await kernelForComponent([base.resolve("lib.dart")], options); + + fs = new MemoryFileSystem(base); + fs.entityForUri(platformDill).writeAsBytesSync(platformDillBytes); + fs + .entityForUri(base.resolve("lib.dart.dill")) + .writeAsBytesSync(serializeComponent(component)); + fs + .entityForUri(base.resolve("repro.dart")) + .writeAsStringSync(files["repro.dart"]); + + options = new CompilerOptions() + ..fileSystem = fs + ..linkedDependencies = [base.resolve("lib.dart.dill")] + ..sdkSummary = platformDill; + + List inputs = [base.resolve("repro.dart")]; + + component = await kernelForComponent(inputs, options); + + List errors = await CompilerContext.runWithOptions( + new ProcessedOptions(options: options, inputs: inputs), + (_) => new Future>.value( + verifyComponent(component, skipPlatform: true))); + + serializeComponent(component); + + if (errors.isNotEmpty) { + throw "Verification failed"; + } +} + +main() { + asyncTest(test); +}