[cfe] Use inferred types on forwarding constructors

Closes #40428

Change-Id: I26bf1e21684605d85312c5e808191ad035eb574b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134289
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2020-02-05 12:26:49 +00:00 committed by commit-bot@chromium.org
parent 12b5e23084
commit d826ecc447
16 changed files with 302 additions and 20 deletions

View file

@ -318,6 +318,7 @@ class KernelTarget extends TargetImplementation {
loader.addNoSuchMethodForwarders(myClasses);
loader.checkMixins(myClasses);
loader.buildOutlineExpressions(loader.coreTypes);
_updateDelayedParameterTypes();
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
return component;
@ -450,6 +451,17 @@ class KernelTarget extends TargetImplementation {
ticker.logMs("Installed synthetic constructors");
}
List<DelayedParameterType> _delayedParameterTypes = <DelayedParameterType>[];
/// Update the type of parameters cloned from parameters with inferred
/// parameter types.
void _updateDelayedParameterTypes() {
for (DelayedParameterType delayedParameterType in _delayedParameterTypes) {
delayedParameterType.updateType();
}
_delayedParameterTypes.clear();
}
ClassBuilder get objectClassBuilder => objectType.declaration;
Class get objectClass => objectClassBuilder.cls;
@ -565,6 +577,9 @@ class KernelTarget extends TargetImplementation {
isFinal: formal.isFinal, isConst: formal.isConst);
if (formal.type != null) {
copy.type = substitute(formal.type, substitutionMap);
} else {
_delayedParameterTypes
.add(new DelayedParameterType(formal, copy, substitutionMap));
}
return copy;
}
@ -1082,3 +1097,21 @@ class KernelDiagnosticReporter
loader.addProblem(message, charOffset, noLength, fileUri, context: context);
}
}
/// Data for updating cloned parameters of parameters with inferred parameter
/// types.
///
/// The type of [source] is not declared so the type of [target] needs to be
/// updated when the type of [source] has been inferred.
class DelayedParameterType {
final VariableDeclaration source;
final VariableDeclaration target;
final Map<TypeParameter, DartType> substitutionMap;
DelayedParameterType(this.source, this.target, this.substitutionMap);
void updateType() {
assert(source.type != null, "No type computed for $source.");
target.type = substitute(source.type, substitutionMap);
}
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2020, 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.
abstract class SuperClass1 {
final String value;
SuperClass1(this.value);
}
abstract class SuperClass2 {
final String value;
SuperClass2(String i) : value = i;
}
class Mixin {}
class NamedMixin1 = SuperClass1 with Mixin;
class NamedMixin2 = SuperClass2 with Mixin;
void main() {
new NamedMixin1('');
new NamedMixin2('');
}
errors() {
new NamedMixin1(0);
new NamedMixin2(0);
}

View file

@ -0,0 +1,32 @@
library;
import self as self;
import "dart:core" as core;
abstract class SuperClass1 extends core::Object {
final field core::String* value;
constructor •(core::String* value) → self::SuperClass1*
;
}
abstract class SuperClass2 extends core::Object {
final field core::String* value;
constructor •(core::String* i) → self::SuperClass2*
;
}
class Mixin extends core::Object {
synthetic constructor •() → self::Mixin*
;
}
class NamedMixin1 = self::SuperClass1 with self::Mixin {
synthetic constructor •(core::String* value) → self::NamedMixin1*
: super self::SuperClass1::•(value)
;
}
class NamedMixin2 = self::SuperClass2 with self::Mixin {
synthetic constructor •(core::String* i) → self::NamedMixin2*
: super self::SuperClass2::•(i)
;
}
static method main() → void
;
static method errors() → dynamic
;

View file

@ -0,0 +1,54 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue40428.dart:28:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
// new NamedMixin1(0);
// ^
//
// pkg/front_end/testcases/general/issue40428.dart:29:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
// new NamedMixin2(0);
// ^
//
import self as self;
import "dart:core" as core;
abstract class SuperClass1 extends core::Object {
final field core::String* value;
constructor •(core::String* value) → self::SuperClass1*
: self::SuperClass1::value = value, super core::Object::•()
;
}
abstract class SuperClass2 extends core::Object {
final field core::String* value;
constructor •(core::String* i) → self::SuperClass2*
: self::SuperClass2::value = i, super core::Object::•()
;
}
class Mixin extends core::Object {
synthetic constructor •() → self::Mixin*
: super core::Object::•()
;
}
class NamedMixin1 = self::SuperClass1 with self::Mixin {
synthetic constructor •(core::String* value) → self::NamedMixin1*
: super self::SuperClass1::•(value)
;
}
class NamedMixin2 = self::SuperClass2 with self::Mixin {
synthetic constructor •(core::String* i) → self::NamedMixin2*
: super self::SuperClass2::•(i)
;
}
static method main() → void {
new self::NamedMixin1::•("");
new self::NamedMixin2::•("");
}
static method errors() → dynamic {
new self::NamedMixin1::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/issue40428.dart:28:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
new NamedMixin1(0);
^" in 0 as{TypeError} core::String*);
new self::NamedMixin2::•(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/issue40428.dart:29:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
new NamedMixin2(0);
^" in 0 as{TypeError} core::String*);
}

View file

@ -0,0 +1,54 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue40428.dart:28:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
// new NamedMixin1(0);
// ^
//
// pkg/front_end/testcases/general/issue40428.dart:29:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
// new NamedMixin2(0);
// ^
//
import self as self;
import "dart:core" as core;
abstract class SuperClass1 extends core::Object {
final field core::String* value;
constructor •(core::String* value) → self::SuperClass1*
: self::SuperClass1::value = value, super core::Object::•()
;
}
abstract class SuperClass2 extends core::Object {
final field core::String* value;
constructor •(core::String* i) → self::SuperClass2*
: self::SuperClass2::value = i, super core::Object::•()
;
}
class Mixin extends core::Object {
synthetic constructor •() → self::Mixin*
: super core::Object::•()
;
}
class NamedMixin1 extends self::SuperClass1 implements self::Mixin {
synthetic constructor •(core::String* value) → self::NamedMixin1*
: super self::SuperClass1::•(value)
;
}
class NamedMixin2 extends self::SuperClass2 implements self::Mixin {
synthetic constructor •(core::String* i) → self::NamedMixin2*
: super self::SuperClass2::•(i)
;
}
static method main() → void {
new self::NamedMixin1::•("");
new self::NamedMixin2::•("");
}
static method errors() → dynamic {
new self::NamedMixin1::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/issue40428.dart:28:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
new NamedMixin1(0);
^" in 0 as{TypeError} core::String*);
new self::NamedMixin2::•(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/issue40428.dart:29:19: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
new NamedMixin2(0);
^" in 0 as{TypeError} core::String*);
}

View file

@ -13,8 +13,9 @@ class Super {
class Class = Super with Mixin;
main() {
// TODO(johnniwinther): The parameter is created before the super constructor
// parameter type is inferred. Set up a way to propagate the inferred type
// to its use sites.
new Class(0);
}
error() {
new Class('');
}

View file

@ -12,9 +12,11 @@ class Super extends core::Object {
;
}
class Class = self::Super with self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic
;
static method error() → dynamic
;

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart:20:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class = self::Super with self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart:20:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart:20:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class extends self::Super implements self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart:20:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -15,8 +15,9 @@ class Super {
class Class = Super with Mixin;
main() {
// TODO(johnniwinther): The parameter is created before the super constructor
// parameter type is inferred. Set up a way to propagate the inferred type
// to its use sites.
new Class(0);
}
error() {
new Class('');
}

View file

@ -12,9 +12,11 @@ class Super extends core::Object {
;
}
class Class = self::Super with self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic
;
static method error() → dynamic
;

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class = self::Super with self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class extends self::Super implements self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class = self::Super with self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// new Class('');
// ^
//
import self as self;
import "dart:core" as core;
@ -14,10 +21,15 @@ class Super extends core::Object {
;
}
class Class extends self::Super implements self::Mixin {
synthetic constructor •(dynamic field) → self::Class*
synthetic constructor •(core::int* field) → self::Class*
: super self::Super::•(field)
;
}
static method main() → dynamic {
new self::Class::•("");
new self::Class::•(0);
}
static method error() → dynamic {
new self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart:22:13: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
new Class('');
^" in "" as{TypeError} core::int*);
}

View file

@ -228,6 +228,7 @@ general/issue38961: TextSerializationFailure
general/issue39344: TextSerializationFailure
general/issue39421: TextSerializationFailure
general/issue39817: TextSerializationFailure
general/issue40428: TextSerializationFailure
general/literals: TextSerializationFailure # Was: Pass
general/local_generic_function: TextSerializationFailure # Was: Pass
general/long_chain_of_typedefs: TextSerializationFailure