| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.resolver; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/scanner.dart'; | |
| 10 | |
| 11 import 'ast.dart'; | 9 import 'ast.dart'; |
| 12 import 'constant.dart'; | 10 import 'constant.dart'; |
| 13 import 'element.dart'; | 11 import 'element.dart'; |
| 14 import 'element_resolver.dart'; | 12 import 'element_resolver.dart'; |
| 15 import 'engine.dart'; | 13 import 'engine.dart'; |
| 16 import 'error.dart'; | 14 import 'error.dart'; |
| 17 import 'error_verifier.dart'; | 15 import 'error_verifier.dart'; |
| 18 import 'html.dart' as ht; | 16 import 'html.dart' as ht; |
| 19 import 'java_core.dart'; | 17 import 'java_core.dart'; |
| 20 import 'java_engine.dart'; | 18 import 'java_engine.dart'; |
| 19 import 'scanner.dart'; |
| 21 import 'scanner.dart' as sc; | 20 import 'scanner.dart' as sc; |
| 22 import 'sdk.dart' show DartSdk, SdkLibrary; | 21 import 'sdk.dart' show DartSdk, SdkLibrary; |
| 23 import 'source.dart'; | 22 import 'source.dart'; |
| 24 import 'static_type_analyzer.dart'; | 23 import 'static_type_analyzer.dart'; |
| 24 import 'type_system.dart'; |
| 25 import 'utilities_dart.dart'; | 25 import 'utilities_dart.dart'; |
| 26 | 26 |
| 27 export 'type_system.dart'; |
| 28 |
| 27 /** | 29 /** |
| 28 * Callback signature used by ImplicitConstructorBuilder to register | 30 * Callback signature used by ImplicitConstructorBuilder to register |
| 29 * computations to be performed, and their dependencies. A call to this | 31 * computations to be performed, and their dependencies. A call to this |
| 30 * callback indicates that [computation] may be used to compute implicit | 32 * callback indicates that [computation] may be used to compute implicit |
| 31 * constructors for [classElement], but that the computation may not be invoked | 33 * constructors for [classElement], but that the computation may not be invoked |
| 32 * until after implicit constructors have been built for [superclassElement]. | 34 * until after implicit constructors have been built for [superclassElement]. |
| 33 */ | 35 */ |
| 34 typedef void ImplicitConstructorBuilderCallback(ClassElement classElement, | 36 typedef void ImplicitConstructorBuilderCallback(ClassElement classElement, |
| 35 ClassElement superclassElement, void computation()); | 37 ClassElement superclassElement, void computation()); |
| 36 | 38 |
| 37 typedef LibraryResolver LibraryResolverFactory(AnalysisContext context); | 39 typedef LibraryResolver LibraryResolverFactory(AnalysisContext context); |
| 38 | 40 |
| 39 typedef ResolverVisitor ResolverVisitorFactory( | 41 typedef ResolverVisitor ResolverVisitorFactory( |
| 40 Library library, Source source, TypeProvider typeProvider); | 42 Library library, Source source, TypeProvider typeProvider); |
| 41 | 43 |
| 42 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor); | 44 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor); |
| 43 | 45 |
| 44 typedef TypeResolverVisitor TypeResolverVisitorFactory( | 46 typedef TypeResolverVisitor TypeResolverVisitorFactory( |
| 45 Library library, Source source, TypeProvider typeProvider); | 47 Library library, Source source, TypeProvider typeProvider); |
| 46 | 48 |
| 47 typedef void VoidFunction(); | 49 typedef void VoidFunction(); |
| 48 | 50 |
| 49 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); | |
| 50 | |
| 51 typedef bool _SubtypeChecker<T>(T t1, T t2); | |
| 52 | |
| 53 /** | 51 /** |
| 54 * Instances of the class `BestPracticesVerifier` traverse an AST structure look
ing for | 52 * Instances of the class `BestPracticesVerifier` traverse an AST structure look
ing for |
| 55 * violations of Dart best practices. | 53 * violations of Dart best practices. |
| 56 */ | 54 */ |
| 57 class BestPracticesVerifier extends RecursiveAstVisitor<Object> { | 55 class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| 58 // static String _HASHCODE_GETTER_NAME = "hashCode"; | 56 // static String _HASHCODE_GETTER_NAME = "hashCode"; |
| 59 | 57 |
| 60 static String _NULL_TYPE_NAME = "Null"; | 58 static String _NULL_TYPE_NAME = "Null"; |
| 61 | 59 |
| 62 static String _TO_INT_METHOD_NAME = "toInt"; | 60 static String _TO_INT_METHOD_NAME = "toInt"; |
| (...skipping 12736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12799 } | 12797 } |
| 12800 } else if (statement is FunctionDeclarationStatement) { | 12798 } else if (statement is FunctionDeclarationStatement) { |
| 12801 FunctionDeclarationStatement fds = statement; | 12799 FunctionDeclarationStatement fds = statement; |
| 12802 scope.hide(fds.functionDeclaration.element); | 12800 scope.hide(fds.functionDeclaration.element); |
| 12803 } | 12801 } |
| 12804 } | 12802 } |
| 12805 } | 12803 } |
| 12806 } | 12804 } |
| 12807 | 12805 |
| 12808 /** | 12806 /** |
| 12809 * Implementation of [TypeSystem] using the strong mode rules. | |
| 12810 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md | |
| 12811 */ | |
| 12812 class StrongTypeSystemImpl implements TypeSystem { | |
| 12813 final _specTypeSystem = new TypeSystemImpl(); | |
| 12814 | |
| 12815 StrongTypeSystemImpl(); | |
| 12816 | |
| 12817 @override | |
| 12818 DartType getLeastUpperBound( | |
| 12819 TypeProvider typeProvider, DartType type1, DartType type2) { | |
| 12820 // TODO(leafp): Implement a strong mode version of this. | |
| 12821 return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2); | |
| 12822 } | |
| 12823 | |
| 12824 // TODO(leafp): Document the rules in play here | |
| 12825 @override | |
| 12826 bool isAssignableTo(DartType fromType, DartType toType) { | |
| 12827 // An actual subtype | |
| 12828 if (isSubtypeOf(fromType, toType)) { | |
| 12829 return true; | |
| 12830 } | |
| 12831 | |
| 12832 // Don't allow implicit downcasts between function types | |
| 12833 // and call method objects, as these will almost always fail. | |
| 12834 if ((fromType is FunctionType && _getCallMethodType(toType) != null) || | |
| 12835 (toType is FunctionType && _getCallMethodType(fromType) != null)) { | |
| 12836 return false; | |
| 12837 } | |
| 12838 | |
| 12839 // If the subtype relation goes the other way, allow the implicit downcast. | |
| 12840 // TODO(leafp): Emit warnings and hints for these in some way. | |
| 12841 // TODO(leafp): Consider adding a flag to disable these? Or just rely on | |
| 12842 // --warnings-as-errors? | |
| 12843 if (isSubtypeOf(toType, fromType) || | |
| 12844 _specTypeSystem.isAssignableTo(toType, fromType)) { | |
| 12845 // TODO(leafp): error if type is known to be exact (literal, | |
| 12846 // instance creation). | |
| 12847 // TODO(leafp): Warn on composite downcast. | |
| 12848 // TODO(leafp): hint on object/dynamic downcast. | |
| 12849 // TODO(leafp): Consider allowing assignment casts. | |
| 12850 return true; | |
| 12851 } | |
| 12852 | |
| 12853 return false; | |
| 12854 } | |
| 12855 | |
| 12856 @override | |
| 12857 bool isSubtypeOf(DartType leftType, DartType rightType) { | |
| 12858 return _isSubtypeOf(leftType, rightType, null); | |
| 12859 } | |
| 12860 | |
| 12861 FunctionType _getCallMethodType(DartType t) { | |
| 12862 if (t is InterfaceType) { | |
| 12863 return t.lookUpInheritedMethod("call")?.type; | |
| 12864 } | |
| 12865 return null; | |
| 12866 } | |
| 12867 | |
| 12868 // Given a type t, if t is an interface type with a call method | |
| 12869 // defined, return the function type for the call method, otherwise | |
| 12870 // return null. | |
| 12871 _GuardedSubtypeChecker<DartType> _guard( | |
| 12872 _GuardedSubtypeChecker<DartType> check) { | |
| 12873 return (DartType t1, DartType t2, Set<Element> visited) { | |
| 12874 Element element = t1.element; | |
| 12875 if (visited == null) { | |
| 12876 visited = new HashSet<Element>(); | |
| 12877 } | |
| 12878 if (element == null || !visited.add(element)) { | |
| 12879 return false; | |
| 12880 } | |
| 12881 try { | |
| 12882 return check(t1, t2, visited); | |
| 12883 } finally { | |
| 12884 visited.remove(element); | |
| 12885 } | |
| 12886 }; | |
| 12887 } | |
| 12888 | |
| 12889 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { | |
| 12890 return (t.isDynamic && dynamicIsBottom) || t.isBottom; | |
| 12891 } | |
| 12892 | |
| 12893 // Guard against loops in the class hierarchy | |
| 12894 /** | |
| 12895 * Check that [f1] is a subtype of [f2]. | |
| 12896 * [fuzzyArrows] indicates whether or not the f1 and f2 should be | |
| 12897 * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated | |
| 12898 * as bottom). | |
| 12899 */ | |
| 12900 bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2, | |
| 12901 {bool fuzzyArrows: true}) { | |
| 12902 final r1s = f1.normalParameterTypes; | |
| 12903 final o1s = f1.optionalParameterTypes; | |
| 12904 final n1s = f1.namedParameterTypes; | |
| 12905 final r2s = f2.normalParameterTypes; | |
| 12906 final o2s = f2.optionalParameterTypes; | |
| 12907 final n2s = f2.namedParameterTypes; | |
| 12908 final ret1 = f1.returnType; | |
| 12909 final ret2 = f2.returnType; | |
| 12910 | |
| 12911 // A -> B <: C -> D if C <: A and | |
| 12912 // either D is void or B <: D | |
| 12913 if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) { | |
| 12914 return false; | |
| 12915 } | |
| 12916 | |
| 12917 // Reject if one has named and the other has optional | |
| 12918 if (n1s.length > 0 && o2s.length > 0) { | |
| 12919 return false; | |
| 12920 } | |
| 12921 if (n2s.length > 0 && o1s.length > 0) { | |
| 12922 return false; | |
| 12923 } | |
| 12924 | |
| 12925 // Rebind _isSubtypeOf for convenience | |
| 12926 _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) => | |
| 12927 _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows); | |
| 12928 | |
| 12929 // f2 has named parameters | |
| 12930 if (n2s.length > 0) { | |
| 12931 // Check that every named parameter in f2 has a match in f1 | |
| 12932 for (String k2 in n2s.keys) { | |
| 12933 if (!n1s.containsKey(k2)) { | |
| 12934 return false; | |
| 12935 } | |
| 12936 if (!parameterSubtype(n2s[k2], n1s[k2])) { | |
| 12937 return false; | |
| 12938 } | |
| 12939 } | |
| 12940 } | |
| 12941 // If we get here, we either have no named parameters, | |
| 12942 // or else the named parameters match and we have no optional | |
| 12943 // parameters | |
| 12944 | |
| 12945 // If f1 has more required parameters, reject | |
| 12946 if (r1s.length > r2s.length) { | |
| 12947 return false; | |
| 12948 } | |
| 12949 | |
| 12950 // If f2 has more required + optional parameters, reject | |
| 12951 if (r2s.length + o2s.length > r1s.length + o1s.length) { | |
| 12952 return false; | |
| 12953 } | |
| 12954 | |
| 12955 // The parameter lists must look like the following at this point | |
| 12956 // where rrr is a region of required, and ooo is a region of optionals. | |
| 12957 // f1: rrr ooo ooo ooo | |
| 12958 // f2: rrr rrr ooo | |
| 12959 int rr = r1s.length; // required in both | |
| 12960 int or = r2s.length - r1s.length; // optional in f1, required in f2 | |
| 12961 int oo = o2s.length; // optional in both | |
| 12962 | |
| 12963 for (int i = 0; i < rr; ++i) { | |
| 12964 if (!parameterSubtype(r2s[i], r1s[i])) { | |
| 12965 return false; | |
| 12966 } | |
| 12967 } | |
| 12968 for (int i = 0, j = rr; i < or; ++i, ++j) { | |
| 12969 if (!parameterSubtype(r2s[j], o1s[i])) { | |
| 12970 return false; | |
| 12971 } | |
| 12972 } | |
| 12973 for (int i = or, j = 0; i < oo; ++i, ++j) { | |
| 12974 if (!parameterSubtype(o2s[j], o1s[i])) { | |
| 12975 return false; | |
| 12976 } | |
| 12977 } | |
| 12978 return true; | |
| 12979 } | |
| 12980 | |
| 12981 bool _isInterfaceSubtypeOf( | |
| 12982 InterfaceType i1, InterfaceType i2, Set<Element> visited) { | |
| 12983 // Guard recursive calls | |
| 12984 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = | |
| 12985 _guard(_isInterfaceSubtypeOf); | |
| 12986 | |
| 12987 if (i1 == i2) { | |
| 12988 return true; | |
| 12989 } | |
| 12990 | |
| 12991 if (i1.element == i2.element) { | |
| 12992 List<DartType> tArgs1 = i1.typeArguments; | |
| 12993 List<DartType> tArgs2 = i2.typeArguments; | |
| 12994 | |
| 12995 assert(tArgs1.length == tArgs2.length); | |
| 12996 | |
| 12997 for (int i = 0; i < tArgs1.length; i++) { | |
| 12998 DartType t1 = tArgs1[i]; | |
| 12999 DartType t2 = tArgs2[i]; | |
| 13000 if (!isSubtypeOf(t1, t2)) { | |
| 13001 return false; | |
| 13002 } | |
| 13003 } | |
| 13004 return true; | |
| 13005 } | |
| 13006 | |
| 13007 if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) { | |
| 13008 return true; | |
| 13009 } | |
| 13010 | |
| 13011 if (i1.isObject) { | |
| 13012 return false; | |
| 13013 } | |
| 13014 | |
| 13015 if (guardedInterfaceSubtype(i1.superclass, i2, visited)) { | |
| 13016 return true; | |
| 13017 } | |
| 13018 | |
| 13019 for (final parent in i1.interfaces) { | |
| 13020 if (guardedInterfaceSubtype(parent, i2, visited)) { | |
| 13021 return true; | |
| 13022 } | |
| 13023 } | |
| 13024 | |
| 13025 for (final parent in i1.mixins) { | |
| 13026 if (guardedInterfaceSubtype(parent, i2, visited)) { | |
| 13027 return true; | |
| 13028 } | |
| 13029 } | |
| 13030 | |
| 13031 return false; | |
| 13032 } | |
| 13033 | |
| 13034 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited, | |
| 13035 {bool dynamicIsBottom: false}) { | |
| 13036 // Guard recursive calls | |
| 13037 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf); | |
| 13038 | |
| 13039 if (t1 == t2) { | |
| 13040 return true; | |
| 13041 } | |
| 13042 | |
| 13043 // The types are void, dynamic, bottom, interface types, function types | |
| 13044 // and type parameters. We proceed by eliminating these different classes | |
| 13045 // from consideration. | |
| 13046 | |
| 13047 // Trivially true. | |
| 13048 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || | |
| 13049 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { | |
| 13050 return true; | |
| 13051 } | |
| 13052 | |
| 13053 // Trivially false. | |
| 13054 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || | |
| 13055 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { | |
| 13056 return false; | |
| 13057 } | |
| 13058 | |
| 13059 // S <: T where S is a type variable | |
| 13060 // T is not dynamic or object (handled above) | |
| 13061 // S != T (handled above) | |
| 13062 // So only true if bound of S is S' and | |
| 13063 // S' <: T | |
| 13064 if (t1 is TypeParameterType) { | |
| 13065 DartType bound = t1.element.bound; | |
| 13066 if (bound == null) return false; | |
| 13067 return guardedSubtype(bound, t2, visited); | |
| 13068 } | |
| 13069 | |
| 13070 if (t2 is TypeParameterType) { | |
| 13071 return false; | |
| 13072 } | |
| 13073 | |
| 13074 if (t1.isVoid || t2.isVoid) { | |
| 13075 return false; | |
| 13076 } | |
| 13077 | |
| 13078 // We've eliminated void, dynamic, bottom, and type parameters. The only | |
| 13079 // cases are the combinations of interface type and function type. | |
| 13080 | |
| 13081 // A function type can only subtype an interface type if | |
| 13082 // the interface type is Function | |
| 13083 if (t1 is FunctionType && t2 is InterfaceType) { | |
| 13084 return t2.isDartCoreFunction; | |
| 13085 } | |
| 13086 | |
| 13087 // An interface type can only subtype a function type if | |
| 13088 // the interface type declares a call method with a type | |
| 13089 // which is a super type of the function type. | |
| 13090 if (t1 is InterfaceType && t2 is FunctionType) { | |
| 13091 var callType = _getCallMethodType(t1); | |
| 13092 return (callType != null) && _isFunctionSubtypeOf(callType, t2); | |
| 13093 } | |
| 13094 | |
| 13095 // Two interface types | |
| 13096 if (t1 is InterfaceType && t2 is InterfaceType) { | |
| 13097 return _isInterfaceSubtypeOf(t1, t2, visited); | |
| 13098 } | |
| 13099 | |
| 13100 return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType); | |
| 13101 } | |
| 13102 | |
| 13103 // TODO(leafp): Document the rules in play here | |
| 13104 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { | |
| 13105 return (t.isDynamic && !dynamicIsBottom) || t.isObject; | |
| 13106 } | |
| 13107 } | |
| 13108 | |
| 13109 /** | |
| 13110 * Instances of this class manage the knowledge of what the set of subtypes are
for a given type. | 12807 * Instances of this class manage the knowledge of what the set of subtypes are
for a given type. |
| 13111 */ | 12808 */ |
| 13112 class SubtypeManager { | 12809 class SubtypeManager { |
| 13113 /** | 12810 /** |
| 13114 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype
s of the | 12811 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype
s of the |
| 13115 * key. | 12812 * key. |
| 13116 */ | 12813 */ |
| 13117 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap = | 12814 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap = |
| 13118 new HashMap<ClassElement, HashSet<ClassElement>>(); | 12815 new HashMap<ClassElement, HashSet<ClassElement>>(); |
| 13119 | 12816 |
| (...skipping 2205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15325 return identical(parent.type, node); | 15022 return identical(parent.type, node); |
| 15326 } | 15023 } |
| 15327 if (parent is SimpleFormalParameter) { | 15024 if (parent is SimpleFormalParameter) { |
| 15328 return identical(parent.type, node); | 15025 return identical(parent.type, node); |
| 15329 } | 15026 } |
| 15330 return false; | 15027 return false; |
| 15331 } | 15028 } |
| 15332 } | 15029 } |
| 15333 | 15030 |
| 15334 /** | 15031 /** |
| 15335 * The interface `TypeSystem` defines the behavior of an object representing | |
| 15336 * the type system. This provides a common location to put methods that act on | |
| 15337 * types but may need access to more global data structures, and it paves the | |
| 15338 * way for a possible future where we may wish to make the type system | |
| 15339 * pluggable. | |
| 15340 */ | |
| 15341 abstract class TypeSystem { | |
| 15342 /** | |
| 15343 * Compute the least upper bound of two types. | |
| 15344 */ | |
| 15345 DartType getLeastUpperBound( | |
| 15346 TypeProvider typeProvider, DartType type1, DartType type2); | |
| 15347 | |
| 15348 /** | |
| 15349 * Return `true` if the [leftType] is assignable to the [rightType] (that is, | |
| 15350 * if leftType <==> rightType). | |
| 15351 */ | |
| 15352 bool isAssignableTo(DartType leftType, DartType rightType); | |
| 15353 | |
| 15354 /** | |
| 15355 * Return `true` if the [leftType] is a subtype of the [rightType] (that is, | |
| 15356 * if leftType <: rightType). | |
| 15357 */ | |
| 15358 bool isSubtypeOf(DartType leftType, DartType rightType); | |
| 15359 | |
| 15360 /** | |
| 15361 * Create either a strong mode or regular type system based on context. | |
| 15362 */ | |
| 15363 static TypeSystem create(AnalysisContext context) { | |
| 15364 return (context.analysisOptions.strongMode) | |
| 15365 ? new StrongTypeSystemImpl() | |
| 15366 : new TypeSystemImpl(); | |
| 15367 } | |
| 15368 } | |
| 15369 | |
| 15370 /** | |
| 15371 * Implementation of [TypeSystem] using the rules in the Dart specification. | |
| 15372 */ | |
| 15373 class TypeSystemImpl implements TypeSystem { | |
| 15374 TypeSystemImpl(); | |
| 15375 | |
| 15376 @override | |
| 15377 DartType getLeastUpperBound( | |
| 15378 TypeProvider typeProvider, DartType type1, DartType type2) { | |
| 15379 // The least upper bound relation is reflexive. | |
| 15380 if (identical(type1, type2)) { | |
| 15381 return type1; | |
| 15382 } | |
| 15383 // The least upper bound of dynamic and any type T is dynamic. | |
| 15384 if (type1.isDynamic) { | |
| 15385 return type1; | |
| 15386 } | |
| 15387 if (type2.isDynamic) { | |
| 15388 return type2; | |
| 15389 } | |
| 15390 // The least upper bound of void and any type T != dynamic is void. | |
| 15391 if (type1.isVoid) { | |
| 15392 return type1; | |
| 15393 } | |
| 15394 if (type2.isVoid) { | |
| 15395 return type2; | |
| 15396 } | |
| 15397 // The least upper bound of bottom and any type T is T. | |
| 15398 if (type1.isBottom) { | |
| 15399 return type2; | |
| 15400 } | |
| 15401 if (type2.isBottom) { | |
| 15402 return type1; | |
| 15403 } | |
| 15404 // Let U be a type variable with upper bound B. The least upper bound of U | |
| 15405 // and a type T is the least upper bound of B and T. | |
| 15406 while (type1 is TypeParameterType) { | |
| 15407 // TODO(paulberry): is this correct in the complex of F-bounded | |
| 15408 // polymorphism? | |
| 15409 DartType bound = (type1 as TypeParameterType).element.bound; | |
| 15410 if (bound == null) { | |
| 15411 bound = typeProvider.objectType; | |
| 15412 } | |
| 15413 type1 = bound; | |
| 15414 } | |
| 15415 while (type2 is TypeParameterType) { | |
| 15416 // TODO(paulberry): is this correct in the context of F-bounded | |
| 15417 // polymorphism? | |
| 15418 DartType bound = (type2 as TypeParameterType).element.bound; | |
| 15419 if (bound == null) { | |
| 15420 bound = typeProvider.objectType; | |
| 15421 } | |
| 15422 type2 = bound; | |
| 15423 } | |
| 15424 // The least upper bound of a function type and an interface type T is the | |
| 15425 // least upper bound of Function and T. | |
| 15426 if (type1 is FunctionType && type2 is InterfaceType) { | |
| 15427 type1 = typeProvider.functionType; | |
| 15428 } | |
| 15429 if (type2 is FunctionType && type1 is InterfaceType) { | |
| 15430 type2 = typeProvider.functionType; | |
| 15431 } | |
| 15432 | |
| 15433 // At this point type1 and type2 should both either be interface types or | |
| 15434 // function types. | |
| 15435 if (type1 is InterfaceType && type2 is InterfaceType) { | |
| 15436 InterfaceType result = | |
| 15437 InterfaceTypeImpl.computeLeastUpperBound(type1, type2); | |
| 15438 if (result == null) { | |
| 15439 return typeProvider.dynamicType; | |
| 15440 } | |
| 15441 return result; | |
| 15442 } else if (type1 is FunctionType && type2 is FunctionType) { | |
| 15443 FunctionType result = | |
| 15444 FunctionTypeImpl.computeLeastUpperBound(type1, type2); | |
| 15445 if (result == null) { | |
| 15446 return typeProvider.functionType; | |
| 15447 } | |
| 15448 return result; | |
| 15449 } else { | |
| 15450 // Should never happen. As a defensive measure, return the dynamic type. | |
| 15451 assert(false); | |
| 15452 return typeProvider.dynamicType; | |
| 15453 } | |
| 15454 } | |
| 15455 | |
| 15456 @override | |
| 15457 bool isAssignableTo(DartType leftType, DartType rightType) { | |
| 15458 return leftType.isAssignableTo(rightType); | |
| 15459 } | |
| 15460 | |
| 15461 @override | |
| 15462 bool isSubtypeOf(DartType leftType, DartType rightType) { | |
| 15463 return leftType.isSubtypeOf(rightType); | |
| 15464 } | |
| 15465 } | |
| 15466 | |
| 15467 /** | |
| 15468 * Instances of the class [UnusedLocalElementsVerifier] traverse an element | 15032 * Instances of the class [UnusedLocalElementsVerifier] traverse an element |
| 15469 * structure looking for cases of [HintCode.UNUSED_ELEMENT], | 15033 * structure looking for cases of [HintCode.UNUSED_ELEMENT], |
| 15470 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. | 15034 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. |
| 15471 */ | 15035 */ |
| 15472 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { | 15036 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { |
| 15473 /** | 15037 /** |
| 15474 * The error listener to which errors will be reported. | 15038 * The error listener to which errors will be reported. |
| 15475 */ | 15039 */ |
| 15476 final AnalysisErrorListener _errorListener; | 15040 final AnalysisErrorListener _errorListener; |
| 15477 | 15041 |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16040 nonFields.add(node); | 15604 nonFields.add(node); |
| 16041 return null; | 15605 return null; |
| 16042 } | 15606 } |
| 16043 | 15607 |
| 16044 @override | 15608 @override |
| 16045 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 15609 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 16046 | 15610 |
| 16047 @override | 15611 @override |
| 16048 Object visitWithClause(WithClause node) => null; | 15612 Object visitWithClause(WithClause node) => null; |
| 16049 } | 15613 } |
| OLD | NEW |