Skip to content

Commit

Permalink
Fixes #946: LanguageFeatures/Instantiate-to-bound/nonfunction_typedef…
Browse files Browse the repository at this point in the history
… tests updated according to the SDK changes, missing tests added.
  • Loading branch information
iarkh committed Nov 17, 2020
1 parent 1ebecda commit afb7f8e
Show file tree
Hide file tree
Showing 31 changed files with 489 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ typedef O<X extends M<N<X>>> = M<N<X>>;

main() {
Expect.equals(
typeOf<M<N<M<dynamic>>>>(),
typeOf<M<N<M<N<dynamic>>>>>(),
typeOf<O>()
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.
*/
/**
* @assertion Instantiate to bound then computes an actual type argument list
* for [G] as follows:
*
* Let [Ui],[1] be [Si], for all [i] in [1 .. k]. (This is the "current value"
* of the bound for type variable [i], at step [1]; in general we will
* consider the current step, [m], and use data for that step, e.g., the bound
* [Ui],[m], to compute the data for step [m + 1]).
*
* Let [-->m] be a relation among the type variables [X1 .. Xk] such that
* [Xp -->m Xq] iff [Xq] occurs in [Up],[m] (so each type variable is related
* to, that is, depends on, every type variable in its bound, possibly
* including itself). Let [==>m] be the transitive closure of [-->m]. For each
* [m], let [Ui],[m+1], for [i] in [1 .. k], be determined by the following
* iterative process:
*
* 1. If there exists a [j] in [1 .. k] such that [Xj ==>m X0j] (that is, if
* the dependency graph has a cycle) let [M1 .. Mp] be the strongly connected
* components (SCCs) with respect to [-->m] (that is, the maximal subsets of
* [X1 .. Xk] where every pair of variables in each subset are related in both
* directions by [==>m]; note that the SCCs are pairwise disjoint; also, they
* are uniquely defined up to reordering, and the order does not matter). Let
* [M] be the union of [M1 .. Mp] (that is, all variables that participate in
* a dependency cycle). Let [i] be in [1 .. k]. If [Xi] does not belong to [M]
* then [Ui,m+1 = Ui,m]. Otherwise there exists a [q] such that [Xi] belongs
* to [Mq]; [Ui,m+1] is then obtained from [Ui,m] by replacing every covariant
* occurrence of a variable in [Mq] by [dynamic], and replacing every
* contravariant occurrence of a variable in [Mq] by [Null].
*
* 2. Otherwise, (if no dependency cycle exists) let [j] be the lowest number
* such that [Xj] occurs in [Up,m] for some [p] and [Xj -/->m Xq] for all [q]
* in [1..k] (that is, [Uj,m] is closed, that is, the current bound of [Xj]
* does not contain any type variables; but [Xj] is being depended on by the
* bound of some other type variable). Then, for all [i] in [1 .. k], [Ui,m+1]
* is obtained from [Ui,m] by replacing every covariant occurrence of [Xj] by
* [Uj,m], and replacing every contravariant occurrence of [Xj] by [Null].
*
* 3. Otherwise, (when no dependencies exist) terminate with the result
* [<U1,m ..., Uk,m>].
* @description Checks that instantiation to bounds works OK for non-function
* typedef with [typedef G<X> = void Function()] type parameter: [typedef G<X> =
* X Function(X); class C<X>; typedef A<X extends G<C<X>>> = C<X>].
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable

import "../../../../Utils/expect.dart";

typedef G<X> = X Function(X);
class C<X> {}

typedef A<X extends G<C<X>>> = C<X>;

main() {
Expect.equals(
typeOf<C<G<C<dynamic>>>>(),
typeOf<A>()
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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.
*/
/**
* @assertion Instantiate to bound then computes an actual type argument list
* for [G] as follows:
*
* Let [Ui],[1] be [Si], for all [i] in [1 .. k]. (This is the "current value"
* of the bound for type variable [i], at step [1]; in general we will
* consider the current step, [m], and use data for that step, e.g., the bound
* [Ui],[m], to compute the data for step [m + 1]).
*
* Let [-->m] be a relation among the type variables [X1 .. Xk] such that
* [Xp -->m Xq] iff [Xq] occurs in [Up],[m] (so each type variable is related
* to, that is, depends on, every type variable in its bound, possibly
* including itself). Let [==>m] be the transitive closure of [-->m]. For each
* [m], let [Ui],[m+1], for [i] in [1 .. k], be determined by the following
* iterative process:
*
* 1. If there exists a [j] in [1 .. k] such that [Xj ==>m X0j] (that is, if
* the dependency graph has a cycle) let [M1 .. Mp] be the strongly connected
* components (SCCs) with respect to [-->m] (that is, the maximal subsets of
* [X1 .. Xk] where every pair of variables in each subset are related in both
* directions by [==>m]; note that the SCCs are pairwise disjoint; also, they
* are uniquely defined up to reordering, and the order does not matter). Let
* [M] be the union of [M1 .. Mp] (that is, all variables that participate in
* a dependency cycle). Let [i] be in [1 .. k]. If [Xi] does not belong to [M]
* then [Ui,m+1 = Ui,m]. Otherwise there exists a [q] such that [Xi] belongs
* to [Mq]; [Ui,m+1] is then obtained from [Ui,m] by replacing every covariant
* occurrence of a variable in [Mq] by [dynamic], and replacing every
* contravariant occurrence of a variable in [Mq] by [Null].
*
* 2. Otherwise, (if no dependency cycle exists) let [j] be the lowest number
* such that [Xj] occurs in [Up,m] for some [p] and [Xj -/->m Xq] for all [q]
* in [1..k] (that is, [Uj,m] is closed, that is, the current bound of [Xj]
* does not contain any type variables; but [Xj] is being depended on by the
* bound of some other type variable). Then, for all [i] in [1 .. k], [Ui,m+1]
* is obtained from [Ui,m] by replacing every covariant occurrence of [Xj] by
* [Uj,m], and replacing every contravariant occurrence of [Xj] by [Null].
*
* 3. Otherwise, (when no dependencies exist) terminate with the result
* [<U1,m ..., Uk,m>].
* @description Checks that instantiation to bounds works OK for [typedef G<X> =
* X Function(X); class C<X, Y>; typedef A<X extends G<A<X,Y>>, Y extends X> =
* C<X, Y>].
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable

import "../../../../Utils/expect.dart";

class C<X, Y> {}
typedef G<X> = X Function(X);
typedef A<X extends G<C<X, Y>>, Y extends X> = C<X, Y>;

main() {
Expect.equals(
typeOf<C<G<C<dynamic, dynamic>>, dynamic>>(),
typeOf<A>()
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.
*/
/**
* @assertion Instantiate to bound then computes an actual type argument list
* for [G] as follows:
*
* Let [Ui],[1] be [Si], for all [i] in [1 .. k]. (This is the "current value"
* of the bound for type variable [i], at step [1]; in general we will
* consider the current step, [m], and use data for that step, e.g., the bound
* [Ui],[m], to compute the data for step [m + 1]).
*
* Let [-->m] be a relation among the type variables [X1 .. Xk] such that
* [Xp -->m Xq] iff [Xq] occurs in [Up],[m] (so each type variable is related
* to, that is, depends on, every type variable in its bound, possibly
* including itself). Let [==>m] be the transitive closure of [-->m]. For each
* [m], let [Ui],[m+1], for [i] in [1 .. k], be determined by the following
* iterative process:
*
* 1. If there exists a [j] in [1 .. k] such that [Xj ==>m X0j] (that is, if
* the dependency graph has a cycle) let [M1 .. Mp] be the strongly connected
* components (SCCs) with respect to [-->m] (that is, the maximal subsets of
* [X1 .. Xk] where every pair of variables in each subset are related in both
* directions by [==>m]; note that the SCCs are pairwise disjoint; also, they
* are uniquely defined up to reordering, and the order does not matter). Let
* [M] be the union of [M1 .. Mp] (that is, all variables that participate in
* a dependency cycle). Let [i] be in [1 .. k]. If [Xi] does not belong to [M]
* then [Ui,m+1 = Ui,m]. Otherwise there exists a [q] such that [Xi] belongs
* to [Mq]; [Ui,m+1] is then obtained from [Ui,m] by replacing every covariant
* occurrence of a variable in [Mq] by [dynamic], and replacing every
* contravariant occurrence of a variable in [Mq] by [Null].
*
* 2. Otherwise, (if no dependency cycle exists) let [j] be the lowest number
* such that [Xj] occurs in [Up,m] for some [p] and [Xj -/->m Xq] for all [q]
* in [1..k] (that is, [Uj,m] is closed, that is, the current bound of [Xj]
* does not contain any type variables; but [Xj] is being depended on by the
* bound of some other type variable). Then, for all [i] in [1 .. k], [Ui,m+1]
* is obtained from [Ui,m] by replacing every covariant occurrence of [Xj] by
* [Uj,m], and replacing every contravariant occurrence of [Xj] by [Null].
*
* 3. Otherwise, (when no dependencies exist) terminate with the result
* [<U1,m ..., Uk,m>].
* @description Checks that instantiation to bounds works OK for [class C<X, Y>;
* typedef G<X> = X Function(X); typedef A<X extends G<C<Y, X>>, Y extends
* G<C<X, Y>>> = C<X, Y>].
*
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable

import "../../../../Utils/expect.dart";

class C<X, Y> {}
typedef G<X> = X Function(X);
typedef A<X extends G<C<Y, X>>, Y extends G<C<X, Y>>> = C<X, Y>;

main() {
Expect.equals(
typeOf<C<G<C<dynamic, dynamic>>, G<C<dynamic, dynamic>>>>(),
typeOf<A>()
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [<U1,m ..., Uk,m>].
* @description Checks that instantiate-to-bounds works as expected for [typedef
* A<X extends FutureOr<C<X>>]
* @Issue 44223
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [<U1,m ..., Uk,m>].
* @description Checks that instantiate-to-bounds works as expected for [typedef
* A<X extends FutureOr<C<X>?>]
* @Issue 44223
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* [<U1,m ..., Uk,m>].
* @description Checks that instantiate-to-bounds works as expected for [typedef
* A<X extends FutureOr<C<X>> = C<X?>]
* @Issue 44223
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
* [<U1,m ..., Uk,m>].
* @description Checks that instantiate-to-bounds works as expected for
* [typedef A<X extends C<X>> = C<X>]
*
* @Issue 44223
* @author iarkh@unipro.ru
*/
// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
Expand All @@ -53,53 +55,54 @@ import "../../../../Utils/expect.dart";
class C<X> {}
typedef A<X extends C<X>> = C<X>;

main() {
A? source;
void test(A source) {
var fsource = toF(source);

F<A<C<dynamic>>?>? target = fsource;
F<C<C<dynamic>>?>? target0 = fsource;
F<A<C<dynamic>>> target = fsource;
F<C<C<dynamic>>> target0 = fsource;

F<A<dynamic>?>? target1 = fsource;
// ^^^^^^^
F<A<dynamic>> target1 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<A<C<C<dynamic>>>?>? target2 = fsource;
// ^^^^^^^
F<A<C<C<dynamic>>>> target2 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<A<C<C<C<dynamic>>>>?>? target3 = fsource;
// ^^^^^^^
F<A<C<C<C<dynamic>>>>> target3 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<A<C<C<C<C<dynamic>>>>>?>? target4 = fsource;
// ^^^^^^^
F<A<C<C<C<C<dynamic>>>>>> target4 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<C<dynamic>?>? target5 = fsource;
// ^^^^^^^
F<C<dynamic>> target5 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<C<C<C<dynamic>>>?>? target6 = fsource;
// ^^^^^^^
F<C<C<C<dynamic>>>> target6 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<C<C<C<C<dynamic>>>>?>? target7 = fsource;
// ^^^^^^^
F<C<C<C<C<dynamic>>>>> target7 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

F<C<C<C<C<C<dynamic>>>>>?>? target8 = fsource;
// ^^^^^^^
F<C<C<C<C<C<dynamic>>>>>> target8 = fsource;
// ^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

void main() {
A();
//^
// [analyzer] unspecified
Expand Down
Loading

0 comments on commit afb7f8e

Please sign in to comment.