Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1117)

Unified Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart

Issue 2870543005: Revert "fix #27256, track type bounds for generic functions" (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Reverting - causing build to fail Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
index 40ab74d8fbf08b51242c71833440bf450bb6560f..5e50cbc9e313f7a667b00c3a8b638c7913e529c5 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
@@ -247,7 +247,7 @@ _normalizeParameter(a) => JS(
return ($a == $dynamic) ? $bottom : $a;
})()''');
-List _canonicalizeArray(definite, array, map) => JS(
+_canonicalizeArray(definite, array, map) => JS(
'',
'''(() => {
let arr = ($definite)
@@ -305,8 +305,8 @@ _createSmall(count, definite, returnType, required) => JS(
class FunctionType extends AbstractFunctionType {
final returnType;
- List args;
- List optionals;
+ dynamic args;
+ dynamic optionals;
final named;
dynamic metadata;
String _stringValue;
@@ -328,7 +328,7 @@ class FunctionType extends AbstractFunctionType {
* that all instances will share.
*
*/
- static create(definite, returnType, List args, extra) {
+ static create(definite, returnType, args, extra) {
// Note that if extra is ever passed as an empty array
// or an empty map, we can end up with semantically
// identical function types that don't canonicalize
@@ -356,7 +356,7 @@ class FunctionType extends AbstractFunctionType {
return _memoizeArray(_fnTypeTypeMap, keys, create);
}
- List _process(List array, metadata) {
+ _process(array, metadata) {
var result = [];
for (var i = 0; JS('bool', '# < #.length', i, array); ++i) {
var arg = JS('', '#[#]', array, i);
@@ -438,12 +438,9 @@ class Typedef extends AbstractFunctionType {
}
}
-/// A type variable, used by [GenericFunctionType] to represent a type formal.
class TypeVariable extends TypeRep {
final String name;
-
TypeVariable(this.name);
-
toString() => name;
}
@@ -451,39 +448,29 @@ class GenericFunctionType extends AbstractFunctionType {
final bool definite;
final _instantiateTypeParts;
final int formalCount;
- final _instantiateTypeBounds;
- List<TypeVariable> _typeFormals;
+ var _typeFormals;
- GenericFunctionType(
- this.definite, instantiateTypeParts, this._instantiateTypeBounds)
+ GenericFunctionType(this.definite, instantiateTypeParts)
: _instantiateTypeParts = instantiateTypeParts,
formalCount = JS('int', '#.length', instantiateTypeParts);
- List<TypeVariable> get typeFormals {
+ get typeFormals {
if (_typeFormals != null) return _typeFormals;
// Extract parameter names from the function parameters.
//
// This is not robust in general for user-defined JS functions, but it
// should handle the functions generated by our compiler.
- //
- // TODO(jmesserly): names of TypeVariables are only used for display
- // purposes, such as when an error happens or if someone calls
- // `Type.toString()`. So we could recover them lazily rather than eagerly.
- // Alternatively we could synthesize new names.
- var str = JS('String', '#.toString()', _instantiateTypeParts);
- var hasParens = str[0] == '(';
- var end = str.indexOf(hasParens ? ')' : '=>');
- if (hasParens) {
- _typeFormals = str
- .substring(1, end)
- .split(',')
- .map((n) => new TypeVariable(n.trim()))
- .toList();
+ var str = JS('', '#.toString()', _instantiateTypeParts);
+ var match = JS('', r'#.match(/\(([^)]*)\)/)', str);
+ if (match != null) {
+ var names = JS('', r'#[1].split(",")', match);
+ return _typeFormals = JS('',
+ '#.map(function(s) { return new #(s.trim()) })', names, TypeVariable);
} else {
- _typeFormals = [new TypeVariable(str.substring(0, end).trim())];
+ var name = JS('', r'#.match(/([^=]*)=>/)[1]', str);
+ return _typeFormals = JS('', '[new #(#.trim())]', TypeVariable, name);
}
- return _typeFormals;
}
instantiate(typeArgs) {
@@ -492,148 +479,44 @@ class GenericFunctionType extends AbstractFunctionType {
parts, parts, parts);
}
- List instantiateTypeBounds(List typeArgs) {
- var boundsFn = _instantiateTypeBounds;
- if (boundsFn == null) {
- // The Dart 1 spec says omitted type parameters have an upper bound of
- // Object. However strong mode assumes `dynamic` for all purposes
- // (such as instantiate to bounds) so we use that here.
- return new List.filled(formalCount, _dynamic);
- }
- // If bounds are recursive, we need to apply type formals and return them.
- return JS('List', '#.apply(null, #)', boundsFn, typeArgs);
- }
-
toString() {
- String s = "<";
- var typeFormals = this.typeFormals;
- var typeBounds = instantiateTypeBounds(typeFormals);
- for (int i = 0, n = typeFormals.length; i < n; i++) {
- if (i != 0) s += ", ";
- s += JS('String', '#[#].name', typeFormals, i);
- var typeBound = typeBounds[i];
- if (!identical(typeBound, _dynamic)) {
- s += " extends $typeBound";
- }
- }
- s += ">" + instantiate(typeFormals).toString();
- return s;
+ return JS('', '"<" + #.join(", ") + ">" + #.toString()', typeFormals,
+ instantiate(typeFormals));
}
+}
- /// Given a [DartType] [type], if [type] is an uninstantiated
- /// parameterized type then instantiate the parameters to their
- /// bounds and return those type arguments.
- ///
- /// See the issue for the algorithm description:
- /// <https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397>
- List instantiateDefaultBounds() {
- var typeFormals = this.typeFormals;
-
- // All type formals
- var all = new HashMap<Object, int>.identity();
- // ground types, by index.
- //
- // For each index, this will be a ground type for the corresponding type
- // formal if known, or it will be the original TypeVariable if we are still
- // solving for it. This array is passed to `instantiateToBounds` as we are
- // progressively solving for type variables.
- var defaults = new List<Object>(typeFormals.length);
- // not ground
- var partials = new Map<TypeVariable, Object>.identity();
-
- var typeBounds = this.instantiateTypeBounds(typeFormals);
- for (var i = 0; i < typeFormals.length; i++) {
- var typeFormal = typeFormals[i];
- var bound = typeBounds[i];
- all[typeFormal] = i;
- if (identical(bound, _dynamic)) {
- defaults[i] = bound;
- } else {
- defaults[i] = typeFormal;
- partials[typeFormal] = bound;
- }
- }
-
- bool hasFreeFormal(Object t) {
- if (partials.containsKey(t)) return true;
-
- // Generic classes and typedefs.
- var typeArgs = getGenericArgs(t);
- if (typeArgs != null) return typeArgs.any(hasFreeFormal);
-
- if (t is GenericFunctionType) {
- return hasFreeFormal(t.instantiate(t.typeFormals));
- }
-
- if (t is FunctionType) {
- return hasFreeFormal(t.returnType) || t.args.any(hasFreeFormal);
- }
-
- return false;
- }
-
- var hasProgress = true;
- while (hasProgress) {
- hasProgress = false;
- for (var typeFormal in partials.keys) {
- var partialBound = partials[typeFormal];
- if (!hasFreeFormal(partialBound)) {
- int index = all[typeFormal];
- defaults[index] = instantiateTypeBounds(defaults)[index];
- partials.remove(typeFormal);
- hasProgress = true;
- break;
- }
- }
- }
-
- // If we stopped making progress, and not all types are ground,
- // then the whole type is malbounded and an error should be reported
- // if errors are requested, and a partially completed type should
- // be returned.
- if (partials.isNotEmpty) {
- throwStrongModeError('Instantiate to bounds failed for type with '
- 'recursive generic bounds: ${typeName(this)}. '
- 'Try passing explicit type arguments.');
- }
-
- return defaults;
- }
+typedef(name, /*FunctionTypeClosure*/ closure) {
+ return new Typedef(name, closure);
}
-typedef(name, closure) => new Typedef(name, closure);
+_functionType(definite, returnType, args, extra) => JS(
+ '',
+ '''(() => {
+ if ($args === void 0 && $extra === void 0) {
+ return new $GenericFunctionType($definite, $returnType);
+ }
+ return $FunctionType.create($definite, $returnType, $args, $extra);
+})()''');
-/// Create a definite function type.
///
-/// No substitution of dynamic for bottom occurs.
-fnType(returnType, List args, extra) =>
- FunctionType.create(true, returnType, args, extra);
-
-/// Create a "fuzzy" function type.
+/// Create a "fuzzy" function type. If any arguments are dynamic
+/// they will be replaced with bottom.
///
-/// If any arguments are dynamic they will be replaced with bottom.
-fnTypeFuzzy(returnType, List args, extra) =>
- FunctionType.create(false, returnType, args, extra);
+functionType(returnType, args, extra) =>
+ _functionType(false, returnType, args, extra);
-/// Creates a definite generic function type.
///
-/// A function type consists of two things: an instantiate function, and an
-/// function that returns a list of upper bound constraints for each
-/// the type formals. Both functions accept the type parameters, allowing us
-/// to substitute values. The upper bound constraints can be omitted if all
-/// of the type parameters use the default upper bound.
+/// Create a definite function type. No substitution of dynamic for
+/// bottom occurs.
///
-/// For example given the type <T extends Iterable<T>>(T) -> T, we can declare
-/// this type with `gFnType(T => [T, [T]], T => [Iterable$(T)])`.\
-gFnType(instantiateFn, typeBounds) =>
- new GenericFunctionType(true, instantiateFn, typeBounds);
-
-gFnTypeFuzzy(instantiateFn, typeBounds) =>
- new GenericFunctionType(false, instantiateFn, typeBounds);
+definiteFunctionType(returnType, args, extra) =>
+ _functionType(true, returnType, args, extra);
+///
/// TODO(vsm): Remove when mirrors is deprecated.
/// This is a temporary workaround to support dart:mirrors, which doesn't
/// understand generic methods.
+///
getFunctionTypeMirror(AbstractFunctionType type) {
if (type is GenericFunctionType) {
var typeArgs = new List.filled(type.formalCount, dynamic);
@@ -642,7 +525,11 @@ getFunctionTypeMirror(AbstractFunctionType type) {
return type;
}
-bool isType(obj) => JS('', '# === #', _getRuntimeType(obj), Type);
+bool isType(obj) => JS(
+ '',
+ '''(() => {
+ return $_getRuntimeType($obj) === $Type;
+ })()''');
String typeName(type) => JS(
'',
@@ -909,32 +796,15 @@ _isSubtype(t1, t2, isCovariant) => JS(
//
// where TFresh is a list of fresh type variables that both g1 and g2 will
// be instantiated with.
+ //
+ // NOTE: this should also verify the bounds of the type parameters of g1
+ // and g2 , but it does not, see this issue:
+ // https://github.com/dart-lang/sdk/issues/27256
if ($t1.formalCount !== $t2.formalCount) return false;
// Using either function's type formals will work as long as they're both
- // instantiated with the same ones. The instantiate operation is guaranteed
- // to avoid capture because it does not depend on its TypeVariable objects,
- // rather it uses JS function parameters to ensure correct binding.
+ // instantiated with the same ones.
let fresh = $t2.typeFormals;
-
- // Check the bounds of the type parameters of g1 and g2.
- // given a type parameter `T1 extends U1` from g1, and a type parameter
- // `T2 extends U2` from g2, we must ensure that:
- //
- // U2 <: U1
- //
- // (Note the reversal of direction -- type formal bounds are contravariant,
- // similar to the function's formal parameter types).
- //
- let t1Bounds = $t1.instantiateTypeBounds(fresh);
- let t2Bounds = $t2.instantiateTypeBounds(fresh);
- // TODO(jmesserly): we could optimize for the common case of no bounds.
- for (let i = 0; i < $t1.formalCount; i++) {
- if (!$_isSubtype(t2Bounds[i], t1Bounds[i], !$isCovariant)) {
- return false;
- }
- }
-
return $isFunctionSubtype(
$t1.instantiate(fresh), $t2.instantiate(fresh), $isCovariant);
}
« no previous file with comments | « pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart ('k') | pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698