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

Unified Diff: pkg/analyzer/lib/src/generated/type_system.dart

Issue 1648063002: Implement the spec's notion of LUB for function types. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix passing test. Created 4 years, 11 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
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/type.dart ('k') | pkg/analyzer/test/generated/type_system_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/type_system.dart
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index b85205c14911c99f52cac721d098a731e4500744..cff5601b570d77c988699669cade20d1367e204e 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -5,6 +5,7 @@
library analyzer.src.generated.type_system;
import 'dart:collection';
+import 'dart:math' as math;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -12,6 +13,7 @@ import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/utilities_dart.dart';
typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
typedef bool _SubtypeChecker<T>(T t1, T t2);
@@ -709,12 +711,7 @@ class TypeSystemImpl implements TypeSystem {
}
return result;
} else if (type1 is FunctionType && type2 is FunctionType) {
- FunctionType result =
- FunctionTypeImpl.computeLeastUpperBound(type1, type2);
- if (result == null) {
- return typeProvider.functionType;
- }
- return result;
+ return _functionLeastUpperBound(typeProvider, type1, type2);
} else {
// Should never happen. As a defensive measure, return the dynamic type.
assert(false);
@@ -723,6 +720,84 @@ class TypeSystemImpl implements TypeSystem {
}
/**
+ * Compute the least upper bound of function types [f] and [g].
+ *
+ * The spec rules for LUB on function types, informally, are pretty simple
+ * (though unsound):
+ *
+ * - If the functions don't have the same number of required parameters,
+ * always return `Function`.
+ *
+ * - Discard any optional named or positional parameters the two types do not
+ * have in common.
+ *
+ * - Compute the LUB of each corresponding pair of parameter and return types.
+ * Return a function type with those types.
+ */
+ DartType _functionLeastUpperBound(
+ TypeProvider provider, FunctionType f, FunctionType g) {
+ // TODO(rnystrom): Right now, this assumes f and g do not have any type
+ // parameters. Revisit that in the presence of generic methods.
+ List<DartType> fRequired = f.normalParameterTypes;
+ List<DartType> gRequired = g.normalParameterTypes;
+
+ // We need some parameter names for in the synthesized function type, so
+ // arbitrarily use f's.
+ List<String> fRequiredNames = f.normalParameterNames;
+ List<String> fPositionalNames = f.optionalParameterNames;
+
+ // If F and G differ in their number of required parameters, then the
+ // least upper bound of F and G is Function.
+ if (fRequired.length != gRequired.length) {
+ return provider.functionType;
+ }
+
+ // Calculate the LUB of each corresponding pair of parameters.
+ List<ParameterElement> parameters = [];
+
+ for (int i = 0; i < fRequired.length; i++) {
+ parameters.add(new ParameterElementImpl.synthetic(
+ fRequiredNames[i],
+ getLeastUpperBound(provider, fRequired[i], gRequired[i]),
+ ParameterKind.REQUIRED));
+ }
+
+ List<DartType> fPositional = f.optionalParameterTypes;
+ List<DartType> gPositional = g.optionalParameterTypes;
+
+ // Ignore any extra optional positional parameters if one has more than the
+ // other.
+ int length = math.min(fPositional.length, gPositional.length);
+ for (int i = 0; i < length; i++) {
+ parameters.add(new ParameterElementImpl.synthetic(
+ fPositionalNames[i],
+ getLeastUpperBound(provider, fPositional[i], gPositional[i]),
+ ParameterKind.POSITIONAL));
+ }
+
+ Map<String, DartType> fNamed = f.namedParameterTypes;
+ Map<String, DartType> gNamed = g.namedParameterTypes;
+ for (String name in fNamed.keys.toSet()..retainAll(gNamed.keys)) {
+ parameters.add(new ParameterElementImpl.synthetic(
+ name,
+ getLeastUpperBound(provider, fNamed[name], gNamed[name]),
+ ParameterKind.NAMED));
+ }
+
+ // Calculate the LUB of the return type.
+ DartType returnType =
+ getLeastUpperBound(provider, f.returnType, g.returnType);
+
+ FunctionElementImpl function = new FunctionElementImpl("", -1);
+ function.synthetic = true;
+ function.returnType = returnType;
+ function.parameters = parameters;
+
+ function.type = new FunctionTypeImpl(function);
+ return function.type;
+ }
+
+ /**
* Instantiate the function type using `dynamic` for all generic parameters.
*/
FunctionType instantiateToBounds(FunctionType function) {
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/type.dart ('k') | pkg/analyzer/test/generated/type_system_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698