mirror of
https://github.com/dart-lang/sdk
synced 2024-09-22 04:41:18 +00:00
62f7ac8c5d
This is a re-fix of dartbug.com/21912, which I previously fixed incorrectly. Previously, our approach to avoiding infinite loops when comparing types was to maintain a set of typedefs being expanded on the stack, and prune the comparison whenever an attempt was made to expand a typedef that was already being expanded. However, this was too strict, since there are legal (non-circular) types which invole expanding a given typedef in reentrant fashion; we can't prune these types without producing incorrect semantics. An example (from the bug report) is the type of f in the code below: typedef T Function2<S, T>(S z); Function2<Function2<A, B>, Function2<B, A>> f; The solution is to maintain the list of typedefs being expanded inside each FunctionTypeImpl object (and InterfaceTypeImpl object) rather than on the stack during the comparison; this allows us to distinguish the situations where we need to prune (those having to do exclusively with expansion of a typedef) from the situations where we shouldn't prune (those having to do with substitution of a type parameter). A beneficial side effect of this change is that code that interacts with types no longer needs to worry about typedef circularities, since the circularities will automatically be pruned while exploring the type definitions. This simplifies the implementation of isAssignableTo, isSubtypeOf, operator==, and hashCode. (Note, however, that code still needs to cope with circularities in the inheritance hierarchy). BUG=dartbug.com/21912 R=brianwilkerson@google.com Review URL: https://codereview.chromium.org//1143003007
23 lines
622 B
Dart
23 lines
622 B
Dart
// Copyright (c) 2015, 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.
|
|
|
|
// Regression test for issue 21912.
|
|
|
|
class A {}
|
|
class B extends A {}
|
|
|
|
typedef T Function2<S, T>(S z);
|
|
typedef B AToB(A x);
|
|
typedef A BToA(B x);
|
|
|
|
void main() {
|
|
{
|
|
Function2<Function2<A, B>, Function2<B, A>> t1;
|
|
Function2<AToB, BToA> t2;
|
|
Function2<Function2<int, double>, Function2<int, double>> left;
|
|
left = t1; /// 01: static type warning
|
|
left = t2; /// 02: static type warning
|
|
}
|
|
}
|