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

Side by Side Diff: lib/runtime/dart_runtime.dart

Issue 1043323002: Update dart_runtime.dart rules (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Fix null handling Created 5 years, 8 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 unified diff | Download patch
« no previous file with comments | « no previous file | test/runtime/dart_runtime_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 dev_compiler.runtime.dart_runtime; 5 library dev_compiler.runtime.dart_runtime;
6 6
7 import 'dart:mirrors'; 7 import 'dart:mirrors';
8 8
9 import 'package:dev_compiler/config.dart'; 9 import 'package:dev_compiler/config.dart';
10 10
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 } else { 45 } else {
46 // For non-null values, val is T => val as T succeeds. 46 // For non-null values, val is T => val as T succeeds.
47 if (instanceOf(obj, staticType)) return obj; 47 if (instanceOf(obj, staticType)) return obj;
48 } 48 }
49 // TODO(vsm): Add message. 49 // TODO(vsm): Add message.
50 throw new CastError(); 50 throw new CastError();
51 } 51 }
52 52
53 bool instanceOf(dynamic obj, Type staticType) { 53 bool instanceOf(dynamic obj, Type staticType) {
54 // This is our 'is' equivalent. 54 // This is our 'is' equivalent.
55 if (obj == null) {
56 // Only true for the Object type.
57 return staticType == Object || staticType == dynamic || staticType == Null;
58 }
59
60 Type runtimeType = obj.runtimeType; 55 Type runtimeType = obj.runtimeType;
61 return _isSubType(reflectType(runtimeType), reflectType(staticType)); 56 return _isSubType(reflectType(runtimeType), reflectType(staticType));
62 } 57 }
63 58
64 bool isGroundType(Type type) { 59 bool isGroundType(Type type) {
65 // These are types allow in is / as expressions. 60 // These are types allowed in is / as expressions.
66 final mirror = reflectType(type); 61 final mirror = reflectType(type);
67 // Disallow functions. 62 return _isGroundTypeMirror(mirror);
68 if (mirror is FunctionTypeMirror) return false;
69 if (mirror is TypedefMirror) return false;
70 // Disallow generic type parameters.
71 if (mirror is TypeVariableMirror) return false;
72
73 if (mirror is ClassMirror) {
74 return _isRawClass(mirror);
75 }
76
77 // Only dynamic should be left. Should this be allowed?
78 // It's not particularly useful.
79 assert(mirror.reflectedType == dynamic);
80 return true;
81 } 63 }
82 64
83 final _primitiveMap = { 65 final _primitiveMap = {
84 'int': int, 66 'int': int,
85 'double': double, 67 'double': double,
86 'num': num, 68 'num': num,
87 'bool': bool, 69 'bool': bool,
88 'String': String, 70 'String': String,
89 }; 71 };
90 72
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 126
145 if (params1.length < params2.length) { 127 if (params1.length < params2.length) {
146 return false; 128 return false;
147 } 129 }
148 130
149 for (int i = 0; i < params2.length; ++i) { 131 for (int i = 0; i < params2.length; ++i) {
150 ParameterMirror p1 = params1[i]; 132 ParameterMirror p1 = params1[i];
151 ParameterMirror p2 = params2[i]; 133 ParameterMirror p2 = params2[i];
152 134
153 // Contravariant parameter types. 135 // Contravariant parameter types.
154 if (!_isSubType(p2.type, p1.type)) { 136 if (!_isSubType(p2.type, p1.type, dynamicIsBottom: true)) {
155 return false; 137 return false;
156 } 138 }
157 139
158 // Optional parameters. 140 // Optional parameters.
159 if (p2.isOptional) { 141 if (p2.isOptional) {
160 // If the base param is optional, the sub param must be optional: 142 // If the base param is optional, the sub param must be optional:
161 if (!p1.isOptional) return false; 143 if (!p1.isOptional) return false;
162 if (!p2.isNamed) { 144 if (!p2.isNamed) {
163 // either neither are named or 145 // either neither are named or
164 if (p1.isNamed) return false; 146 if (p1.isNamed) return false;
(...skipping 19 matching lines...) Expand all
184 bool _isClassSubType(ClassMirror m1, ClassMirror m2) { 166 bool _isClassSubType(ClassMirror m1, ClassMirror m2) {
185 // TODO(vsm): Consider some caching for efficiency here. 167 // TODO(vsm): Consider some caching for efficiency here.
186 168
187 // We support Dart's covariant generics with the caveat that we do not 169 // We support Dart's covariant generics with the caveat that we do not
188 // substitute bottom for dynamic in subtyping rules. 170 // substitute bottom for dynamic in subtyping rules.
189 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow: 171 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
190 // - S !<: S<T1, ..., Tn> 172 // - S !<: S<T1, ..., Tn>
191 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn> 173 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
192 if (m1 == m2) return true; 174 if (m1 == m2) return true;
193 175
194 if (m1.hasReflectedType && m1.reflectedType == Object) return false; 176 if (_isTop(m1)) return false;
195 177
196 // Check if m1 and m2 have the same raw type. If so, check covariance on 178 // Check if m1 and m2 have the same raw type. If so, check covariance on
197 // type parameters. 179 // type parameters.
198 if (m1.originalDeclaration == m2.originalDeclaration) { 180 if (m1.originalDeclaration == m2.originalDeclaration) {
181 if (_isRawClass(m2)) return true;
182 if (_isRawClass(m1)) return false;
183
199 final typeArguments1 = m1.typeArguments; 184 final typeArguments1 = m1.typeArguments;
200 final typeArguments2 = m2.typeArguments; 185 final typeArguments2 = m2.typeArguments;
201 final length = typeArguments1.length; 186 final length = typeArguments1.length;
202 if (typeArguments2.length == 0) { 187 assert(typeArguments1.isNotEmpty && typeArguments2.isNotEmpty);
203 // m2 is the raw form of m1
204 return true;
205 } else if (typeArguments1.length == 0) {
206 // m1 is raw, but m2 is not
207 return false;
208 }
209 assert(typeArguments2.length == length); 188 assert(typeArguments2.length == length);
210 for (var i = 0; i < length; ++i) { 189 for (var i = 0; i < length; ++i) {
211 var typeArgument1 = typeArguments1[i]; 190 var typeArgument1 = typeArguments1[i];
212 var typeArgument2 = typeArguments2[i]; 191 var typeArgument2 = typeArguments2[i];
213 if (!_isSubType(typeArgument1, typeArgument2)) { 192 if (!_isSubType(typeArgument1, typeArgument2)) {
214 return false; 193 return false;
215 } 194 }
216 } 195 }
217 return true; 196 return true;
218 } 197 }
219 198
220 // Check superclass. 199 // Check superclass.
221 if (_isClassSubType(m1.superclass, m2)) return true; 200 if (_isClassSubType(m1.superclass, m2)) return true;
222 201
202 // Check for mixins. The mixin getter returns the original class if there is
203 // no mixin.
204 if (m1 != m1.mixin && _isClassSubType(m1.mixin, m2)) return true;
205
223 // Check interfaces. 206 // Check interfaces.
224 for (final parent in m1.superinterfaces) { 207 for (final parent in m1.superinterfaces) {
225 if (_isClassSubType(parent, m2)) return true; 208 if (_isClassSubType(parent, m2)) return true;
226 } 209 }
227 210
228 return false; 211 return false;
229 } 212 }
230 213
214 final _dynamicMirror = reflectType(dynamic);
215 final _objectMirror = reflectType(Object);
216 final _nullMirror = reflectType(Null);
Jennifer Messerly 2015/04/02 18:24:38 fyi, I think this is unused now
vsm 2015/04/06 22:28:14 removed
217
218 bool _isBottom(TypeMirror t, {bool dynamicIsBottom: false}) {
219 if (t == _dynamicMirror && dynamicIsBottom) return true;
220 // TODO(vsm): Do we need an explicit representation of Bottom?
221 return false;
222 }
223
224 bool _isTop(TypeMirror t, {bool dynamicIsBottom: false}) {
225 if (t == _dynamicMirror && !dynamicIsBottom) return true;
226 if (t == _objectMirror) return true;
227 return false;
228 }
229
230 bool _isGroundTypeMirror(TypeMirror mirror) {
231 // Disallow generic type parameters.
Leaf 2015/04/03 00:34:02 More like // type parameters shouldn't happen here
vsm 2015/04/06 22:28:14 Done.
232 assert(mirror is! TypeVariableMirror);
233
234 // Allow only 'raw' functions.
235 if (mirror is TypedefMirror) {
236 return _isRawFunction(mirror.referent);
237 }
238 if (mirror is FunctionTypeMirror) {
239 return _isRawFunction(mirror);
240 }
241
242 // Allow only 'raw' classes.
243 if (mirror is ClassMirror) {
244 return _isRawClass(mirror);
245 }
246
247 // Only dynamic should be left. Should this be allowed?
248 // It's not particularly useful.
249 assert(mirror.reflectedType == dynamic);
250 return true;
251 }
252
253 bool _isRawFunction(FunctionTypeMirror mirror) {
254 var returnType = mirror.returnType;
255 if (!_isTop(returnType)) return false;
256 for (var parameter in mirror.parameters) {
257 var paramType = parameter.type;
258 if (!_isBottom(paramType, dynamicIsBottom: true)) return false;
259 }
260 return true;
261 }
262
231 bool _isRawClass(ClassMirror mirror) { 263 bool _isRawClass(ClassMirror mirror) {
232 // Allow only raw types. 264 // Allow only raw types.
233 if (mirror == mirror.originalDeclaration) return true; 265 if (mirror == mirror.originalDeclaration) return true;
234 final dynamicMirror = reflectType(dynamic);
235 for (var typeArgument in mirror.typeArguments) { 266 for (var typeArgument in mirror.typeArguments) {
236 if (typeArgument != dynamicMirror) return false; 267 if (!_isTop(typeArgument)) return false;
Leaf 2015/04/03 00:34:02 This treats List<Object> as a raw type. This is m
vsm 2015/04/06 22:28:14 Hmm, both: - List<Object> <: List<dynamic> - List<
237 } 268 }
238 return true; 269 return true;
239 } 270 }
240 271
241 TypeMirror _canonicalizeTypeMirror(TypeMirror t) { 272 TypeMirror _canonicalizeTypeMirror(TypeMirror t) {
242 if (t is TypedefMirror) { 273 if (t is TypedefMirror) {
243 // We canonicalize Typedefs to their underlying function types. 274 // We canonicalize Typedefs to their underlying function types.
244 t = (t as TypedefMirror).referent; 275 t = (t as TypedefMirror).referent;
245 } 276 }
246 if (t is ClassMirror && _isRawClass(t)) { 277 if (t is ClassMirror && _isRawClass(t)) {
247 // We canonicalize T<dynamic> to T. 278 // We canonicalize T<dynamic> to T.
248 t = t.originalDeclaration; 279 t = t.originalDeclaration;
249 } 280 }
250 return t; 281 return t;
251 } 282 }
252 283
253 bool _reflects(TypeMirror mirror, Type t) { 284 bool _reflects(TypeMirror mirror, Type t) {
254 return mirror.hasReflectedType && mirror.reflectedType == t; 285 return mirror.hasReflectedType && mirror.reflectedType == t;
255 } 286 }
256 287
257 bool _isSubType(TypeMirror t1, TypeMirror t2) { 288 bool _isSubType(TypeMirror t1, TypeMirror t2, {bool dynamicIsBottom: false}) {
258 t1 = _canonicalizeTypeMirror(t1); 289 t1 = _canonicalizeTypeMirror(t1);
259 t2 = _canonicalizeTypeMirror(t2); 290 t2 = _canonicalizeTypeMirror(t2);
260 291
292 if (t1 is TypeVariableMirror) {
293 t1 = t1.upperBound;
294 }
295
261 if (t1 == t2) return true; 296 if (t1 == t2) return true;
262 297
263 // In Dart, dynamic is effectively both top and bottom. 298 // Trivially true.
264 // Here, we treat dynamic as top - the base type of everything. 299 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
Leaf 2015/04/03 00:34:01 I think this makes dynamic <: Object, which I thin
vsm 2015/04/06 22:28:14 Hmm, I thought we added this with the new rule. :
265 if (_reflects(t1, dynamic)) return false; 300 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
266 if (_reflects(t2, dynamic)) return true; 301 return true;
302 }
267 303
268 // Object only subtypes dynamic and Object. 304 // Trivially false.
269 if (_reflects(t2, Object)) return true; 305 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
270 if (_reflects(t1, Object)) return false; 306 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
307 return false;
308 }
271 309
272 // "Traditional" name-based subtype check. 310 // "Traditional" name-based subtype check.
273 final c1 = t1 as ClassMirror; 311 final c1 = t1 as ClassMirror;
274 final c2 = t2 as ClassMirror; 312 final c2 = t2 as ClassMirror;
275 if (_isClassSubType(c1, c2)) { 313 if (_isClassSubType(c1, c2)) {
276 return true; 314 return true;
277 } 315 }
278 316
279 // Function subtyping. 317 // Function subtyping.
280 // Note: it appears under the hood all Dart functions map to a class / hidden type 318 // Note: it appears under the hood all Dart functions map to a class / hidden type
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 ret1 = call1.returnType; 353 ret1 = call1.returnType;
316 params1 = call1.parameters; 354 params1 = call1.parameters;
317 } 355 }
318 356
319 // Any type that implements a call method implicitly subtypes Function. 357 // Any type that implements a call method implicitly subtypes Function.
320 if (_reflects(c2, Function)) return true; 358 if (_reflects(c2, Function)) return true;
321 359
322 // Check structural function subtyping 360 // Check structural function subtyping
323 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters); 361 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters);
324 } 362 }
OLDNEW
« no previous file with comments | « no previous file | test/runtime/dart_runtime_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698