mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:27:17 +00:00
88400bdc42
Number of parent type arguments in function types is critical for instantiation and subtype checks when there are nested generic function types. So it is important to update number of parent type arguments when parent function type is updated. This change adds mechanism for updating number of parent type arguments and uses the new mechanism in 2 cases: 1) When a type parameter is substituted during type instantiation. The substituted type can have nested generic function types and it should be updated if substituted inside another generic function type. 2) When creating a constructor tear-off for a generic class. Parameter types of the constructor could have nested generic function types and they should be updated as tear-off itself is a generic function. TEST=language/function_subtype/generic_function_type_substitution_test TEST=language/regress/regress50905_test Fixes https://github.com/dart-lang/sdk/issues/50614 Fixes https://github.com/dart-lang/sdk/issues/50905 Change-Id: If13baa420939f5ac002ce32f3909953fb6998bd2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/278525 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
49 lines
1.4 KiB
Dart
49 lines
1.4 KiB
Dart
// Copyright (c) 2023, 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.
|
|
|
|
// Verifies that constructor tear-off of a generic class
|
|
// has a correct type and can be called via Function.apply.
|
|
//
|
|
// Regression test for https://github.com/dart-lang/sdk/issues/50905.
|
|
|
|
import 'package:expect/expect.dart';
|
|
|
|
class A<T> {
|
|
A({required T Function() x}) {
|
|
Expect.equals(f1, x);
|
|
}
|
|
}
|
|
|
|
class B<T> {
|
|
B({required Map<S, T> Function<S>() x}) {
|
|
Expect.equals(f2, x);
|
|
}
|
|
}
|
|
|
|
int f1() => 0;
|
|
Map<U, int> f2<U>() => {};
|
|
|
|
A<V> t1<V>({required V Function() x}) => throw 'unused';
|
|
A<int> t2({required int Function() x}) => throw 'unused';
|
|
B<V> t3<V>({required Map<U, V> Function<U>() x}) => throw 'unused';
|
|
B<int> t4({required Map<U, int> Function<U>() x}) => throw 'unused';
|
|
|
|
void main() {
|
|
Function c1 = A.new;
|
|
Expect.equals(t1.runtimeType.toString(), c1.runtimeType.toString());
|
|
|
|
Function c2 = A<int>.new;
|
|
Expect.equals(t2.runtimeType.toString(), c2.runtimeType.toString());
|
|
final o2 = Function.apply(c2, [], {#x: f1});
|
|
Expect.isTrue(o2 is A<int>);
|
|
|
|
Function c3 = B.new;
|
|
Expect.equals(t3.runtimeType.toString(), c3.runtimeType.toString());
|
|
|
|
Function c4 = B<int>.new;
|
|
Expect.equals(t4.runtimeType.toString(), c4.runtimeType.toString());
|
|
final o4 = Function.apply(c4, [], {#x: f2});
|
|
Expect.isTrue(o4 is B<int>);
|
|
}
|