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

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

Issue 1407923009: move TypeSystem classes to their own file (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 91f49200bb8ba8c9299b6b07be71c78df2ecfde6..eece655cd05407e8e8272c2013139e7c23953036 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -6,8 +6,6 @@ library engine.resolver;
import 'dart:collection';
-import 'package:analyzer/src/generated/scanner.dart';
-
import 'ast.dart';
import 'constant.dart';
import 'element.dart';
@@ -18,12 +16,16 @@ import 'error_verifier.dart';
import 'html.dart' as ht;
import 'java_core.dart';
import 'java_engine.dart';
+import 'scanner.dart';
import 'scanner.dart' as sc;
import 'sdk.dart' show DartSdk, SdkLibrary;
import 'source.dart';
import 'static_type_analyzer.dart';
+import 'type_system.dart';
import 'utilities_dart.dart';
+export 'type_system.dart';
+
/**
* Callback signature used by ImplicitConstructorBuilder to register
* computations to be performed, and their dependencies. A call to this
@@ -46,10 +48,6 @@ typedef TypeResolverVisitor TypeResolverVisitorFactory(
typedef void VoidFunction();
-typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
-
-typedef bool _SubtypeChecker<T>(T t1, T t2);
-
/**
* Instances of the class `BestPracticesVerifier` traverse an AST structure looking for
* violations of Dart best practices.
@@ -12806,307 +12804,6 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
}
/**
- * Implementation of [TypeSystem] using the strong mode rules.
- * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
- */
-class StrongTypeSystemImpl implements TypeSystem {
- final _specTypeSystem = new TypeSystemImpl();
-
- StrongTypeSystemImpl();
-
- @override
- DartType getLeastUpperBound(
- TypeProvider typeProvider, DartType type1, DartType type2) {
- // TODO(leafp): Implement a strong mode version of this.
- return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2);
- }
-
- // TODO(leafp): Document the rules in play here
- @override
- bool isAssignableTo(DartType fromType, DartType toType) {
- // An actual subtype
- if (isSubtypeOf(fromType, toType)) {
- return true;
- }
-
- // Don't allow implicit downcasts between function types
- // and call method objects, as these will almost always fail.
- if ((fromType is FunctionType && _getCallMethodType(toType) != null) ||
- (toType is FunctionType && _getCallMethodType(fromType) != null)) {
- return false;
- }
-
- // If the subtype relation goes the other way, allow the implicit downcast.
- // TODO(leafp): Emit warnings and hints for these in some way.
- // TODO(leafp): Consider adding a flag to disable these? Or just rely on
- // --warnings-as-errors?
- if (isSubtypeOf(toType, fromType) ||
- _specTypeSystem.isAssignableTo(toType, fromType)) {
- // TODO(leafp): error if type is known to be exact (literal,
- // instance creation).
- // TODO(leafp): Warn on composite downcast.
- // TODO(leafp): hint on object/dynamic downcast.
- // TODO(leafp): Consider allowing assignment casts.
- return true;
- }
-
- return false;
- }
-
- @override
- bool isSubtypeOf(DartType leftType, DartType rightType) {
- return _isSubtypeOf(leftType, rightType, null);
- }
-
- FunctionType _getCallMethodType(DartType t) {
- if (t is InterfaceType) {
- return t.lookUpInheritedMethod("call")?.type;
- }
- return null;
- }
-
- // Given a type t, if t is an interface type with a call method
- // defined, return the function type for the call method, otherwise
- // return null.
- _GuardedSubtypeChecker<DartType> _guard(
- _GuardedSubtypeChecker<DartType> check) {
- return (DartType t1, DartType t2, Set<Element> visited) {
- Element element = t1.element;
- if (visited == null) {
- visited = new HashSet<Element>();
- }
- if (element == null || !visited.add(element)) {
- return false;
- }
- try {
- return check(t1, t2, visited);
- } finally {
- visited.remove(element);
- }
- };
- }
-
- bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
- return (t.isDynamic && dynamicIsBottom) || t.isBottom;
- }
-
- // Guard against loops in the class hierarchy
- /**
- * Check that [f1] is a subtype of [f2].
- * [fuzzyArrows] indicates whether or not the f1 and f2 should be
- * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
- * as bottom).
- */
- bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
- {bool fuzzyArrows: true}) {
- final r1s = f1.normalParameterTypes;
- final o1s = f1.optionalParameterTypes;
- final n1s = f1.namedParameterTypes;
- final r2s = f2.normalParameterTypes;
- final o2s = f2.optionalParameterTypes;
- final n2s = f2.namedParameterTypes;
- final ret1 = f1.returnType;
- final ret2 = f2.returnType;
-
- // A -> B <: C -> D if C <: A and
- // either D is void or B <: D
- if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) {
- return false;
- }
-
- // Reject if one has named and the other has optional
- if (n1s.length > 0 && o2s.length > 0) {
- return false;
- }
- if (n2s.length > 0 && o1s.length > 0) {
- return false;
- }
-
- // Rebind _isSubtypeOf for convenience
- _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) =>
- _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows);
-
- // f2 has named parameters
- if (n2s.length > 0) {
- // Check that every named parameter in f2 has a match in f1
- for (String k2 in n2s.keys) {
- if (!n1s.containsKey(k2)) {
- return false;
- }
- if (!parameterSubtype(n2s[k2], n1s[k2])) {
- return false;
- }
- }
- }
- // If we get here, we either have no named parameters,
- // or else the named parameters match and we have no optional
- // parameters
-
- // If f1 has more required parameters, reject
- if (r1s.length > r2s.length) {
- return false;
- }
-
- // If f2 has more required + optional parameters, reject
- if (r2s.length + o2s.length > r1s.length + o1s.length) {
- return false;
- }
-
- // The parameter lists must look like the following at this point
- // where rrr is a region of required, and ooo is a region of optionals.
- // f1: rrr ooo ooo ooo
- // f2: rrr rrr ooo
- int rr = r1s.length; // required in both
- int or = r2s.length - r1s.length; // optional in f1, required in f2
- int oo = o2s.length; // optional in both
-
- for (int i = 0; i < rr; ++i) {
- if (!parameterSubtype(r2s[i], r1s[i])) {
- return false;
- }
- }
- for (int i = 0, j = rr; i < or; ++i, ++j) {
- if (!parameterSubtype(r2s[j], o1s[i])) {
- return false;
- }
- }
- for (int i = or, j = 0; i < oo; ++i, ++j) {
- if (!parameterSubtype(o2s[j], o1s[i])) {
- return false;
- }
- }
- return true;
- }
-
- bool _isInterfaceSubtypeOf(
- InterfaceType i1, InterfaceType i2, Set<Element> visited) {
- // Guard recursive calls
- _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype =
- _guard(_isInterfaceSubtypeOf);
-
- if (i1 == i2) {
- return true;
- }
-
- if (i1.element == i2.element) {
- List<DartType> tArgs1 = i1.typeArguments;
- List<DartType> tArgs2 = i2.typeArguments;
-
- assert(tArgs1.length == tArgs2.length);
-
- for (int i = 0; i < tArgs1.length; i++) {
- DartType t1 = tArgs1[i];
- DartType t2 = tArgs2[i];
- if (!isSubtypeOf(t1, t2)) {
- return false;
- }
- }
- return true;
- }
-
- if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
- return true;
- }
-
- if (i1.isObject) {
- return false;
- }
-
- if (guardedInterfaceSubtype(i1.superclass, i2, visited)) {
- return true;
- }
-
- for (final parent in i1.interfaces) {
- if (guardedInterfaceSubtype(parent, i2, visited)) {
- return true;
- }
- }
-
- for (final parent in i1.mixins) {
- if (guardedInterfaceSubtype(parent, i2, visited)) {
- return true;
- }
- }
-
- return false;
- }
-
- bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
- {bool dynamicIsBottom: false}) {
- // Guard recursive calls
- _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf);
-
- if (t1 == t2) {
- return true;
- }
-
- // The types are void, dynamic, bottom, interface types, function types
- // and type parameters. We proceed by eliminating these different classes
- // from consideration.
-
- // Trivially true.
- if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
- _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
- return true;
- }
-
- // Trivially false.
- if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
- _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
- return false;
- }
-
- // S <: T where S is a type variable
- // T is not dynamic or object (handled above)
- // S != T (handled above)
- // So only true if bound of S is S' and
- // S' <: T
- if (t1 is TypeParameterType) {
- DartType bound = t1.element.bound;
- if (bound == null) return false;
- return guardedSubtype(bound, t2, visited);
- }
-
- if (t2 is TypeParameterType) {
- return false;
- }
-
- if (t1.isVoid || t2.isVoid) {
- return false;
- }
-
- // We've eliminated void, dynamic, bottom, and type parameters. The only
- // cases are the combinations of interface type and function type.
-
- // A function type can only subtype an interface type if
- // the interface type is Function
- if (t1 is FunctionType && t2 is InterfaceType) {
- return t2.isDartCoreFunction;
- }
-
- // An interface type can only subtype a function type if
- // the interface type declares a call method with a type
- // which is a super type of the function type.
- if (t1 is InterfaceType && t2 is FunctionType) {
- var callType = _getCallMethodType(t1);
- return (callType != null) && _isFunctionSubtypeOf(callType, t2);
- }
-
- // Two interface types
- if (t1 is InterfaceType && t2 is InterfaceType) {
- return _isInterfaceSubtypeOf(t1, t2, visited);
- }
-
- return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
- }
-
- // TODO(leafp): Document the rules in play here
- bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
- return (t.isDynamic && !dynamicIsBottom) || t.isObject;
- }
-}
-
-/**
* Instances of this class manage the knowledge of what the set of subtypes are for a given type.
*/
class SubtypeManager {
@@ -15332,139 +15029,6 @@ class TypeResolverVisitor extends ScopedVisitor {
}
/**
- * The interface `TypeSystem` defines the behavior of an object representing
- * the type system. This provides a common location to put methods that act on
- * types but may need access to more global data structures, and it paves the
- * way for a possible future where we may wish to make the type system
- * pluggable.
- */
-abstract class TypeSystem {
- /**
- * Compute the least upper bound of two types.
- */
- DartType getLeastUpperBound(
- TypeProvider typeProvider, DartType type1, DartType type2);
-
- /**
- * Return `true` if the [leftType] is assignable to the [rightType] (that is,
- * if leftType <==> rightType).
- */
- bool isAssignableTo(DartType leftType, DartType rightType);
-
- /**
- * Return `true` if the [leftType] is a subtype of the [rightType] (that is,
- * if leftType <: rightType).
- */
- bool isSubtypeOf(DartType leftType, DartType rightType);
-
- /**
- * Create either a strong mode or regular type system based on context.
- */
- static TypeSystem create(AnalysisContext context) {
- return (context.analysisOptions.strongMode)
- ? new StrongTypeSystemImpl()
- : new TypeSystemImpl();
- }
-}
-
-/**
- * Implementation of [TypeSystem] using the rules in the Dart specification.
- */
-class TypeSystemImpl implements TypeSystem {
- TypeSystemImpl();
-
- @override
- DartType getLeastUpperBound(
- TypeProvider typeProvider, DartType type1, DartType type2) {
- // The least upper bound relation is reflexive.
- if (identical(type1, type2)) {
- return type1;
- }
- // The least upper bound of dynamic and any type T is dynamic.
- if (type1.isDynamic) {
- return type1;
- }
- if (type2.isDynamic) {
- return type2;
- }
- // The least upper bound of void and any type T != dynamic is void.
- if (type1.isVoid) {
- return type1;
- }
- if (type2.isVoid) {
- return type2;
- }
- // The least upper bound of bottom and any type T is T.
- if (type1.isBottom) {
- return type2;
- }
- if (type2.isBottom) {
- return type1;
- }
- // Let U be a type variable with upper bound B. The least upper bound of U
- // and a type T is the least upper bound of B and T.
- while (type1 is TypeParameterType) {
- // TODO(paulberry): is this correct in the complex of F-bounded
- // polymorphism?
- DartType bound = (type1 as TypeParameterType).element.bound;
- if (bound == null) {
- bound = typeProvider.objectType;
- }
- type1 = bound;
- }
- while (type2 is TypeParameterType) {
- // TODO(paulberry): is this correct in the context of F-bounded
- // polymorphism?
- DartType bound = (type2 as TypeParameterType).element.bound;
- if (bound == null) {
- bound = typeProvider.objectType;
- }
- type2 = bound;
- }
- // The least upper bound of a function type and an interface type T is the
- // least upper bound of Function and T.
- if (type1 is FunctionType && type2 is InterfaceType) {
- type1 = typeProvider.functionType;
- }
- if (type2 is FunctionType && type1 is InterfaceType) {
- type2 = typeProvider.functionType;
- }
-
- // At this point type1 and type2 should both either be interface types or
- // function types.
- if (type1 is InterfaceType && type2 is InterfaceType) {
- InterfaceType result =
- InterfaceTypeImpl.computeLeastUpperBound(type1, type2);
- if (result == null) {
- return typeProvider.dynamicType;
- }
- return result;
- } else if (type1 is FunctionType && type2 is FunctionType) {
- FunctionType result =
- FunctionTypeImpl.computeLeastUpperBound(type1, type2);
- if (result == null) {
- return typeProvider.functionType;
- }
- return result;
- } else {
- // Should never happen. As a defensive measure, return the dynamic type.
- assert(false);
- return typeProvider.dynamicType;
- }
- }
-
- @override
- bool isAssignableTo(DartType leftType, DartType rightType) {
- return leftType.isAssignableTo(rightType);
- }
-
- @override
- bool isSubtypeOf(DartType leftType, DartType rightType) {
- return leftType.isSubtypeOf(rightType);
- }
-}
-
-/**
* Instances of the class [UnusedLocalElementsVerifier] traverse an element
* structure looking for cases of [HintCode.UNUSED_ELEMENT],
* [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698