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

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: Handle mixins 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 if (obj == null) { 55 if (obj == null) {
56 // Only true for the Object type. 56 // Only true for the Object type.
57 return staticType == Object || staticType == dynamic || staticType == Null; 57 return staticType == Object || staticType == dynamic || staticType == Null;
58 } 58 }
59 59
60 Type runtimeType = obj.runtimeType; 60 Type runtimeType = obj.runtimeType;
61 return _isSubType(reflectType(runtimeType), reflectType(staticType)); 61 return _isSubType(reflectType(runtimeType), reflectType(staticType));
62 } 62 }
63 63
64 bool isGroundType(Type type) { 64 bool isGroundType(Type type) {
65 // These are types allow in is / as expressions. 65 // These are types allowed in is / as expressions.
66 final mirror = reflectType(type); 66 final mirror = reflectType(type);
67 // Disallow functions. 67 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 } 68 }
82 69
83 final _primitiveMap = { 70 final _primitiveMap = {
84 'int': int, 71 'int': int,
85 'double': double, 72 'double': double,
86 'num': num, 73 'num': num,
87 'bool': bool, 74 'bool': bool,
88 'String': String, 75 'String': String,
89 }; 76 };
90 77
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 131
145 if (params1.length < params2.length) { 132 if (params1.length < params2.length) {
146 return false; 133 return false;
147 } 134 }
148 135
149 for (int i = 0; i < params2.length; ++i) { 136 for (int i = 0; i < params2.length; ++i) {
150 ParameterMirror p1 = params1[i]; 137 ParameterMirror p1 = params1[i];
151 ParameterMirror p2 = params2[i]; 138 ParameterMirror p2 = params2[i];
152 139
153 // Contravariant parameter types. 140 // Contravariant parameter types.
154 if (!_isSubType(p2.type, p1.type)) { 141 if (!_isSubType(p2.type, p1.type, dynamicIsBottom: true)) {
155 return false; 142 return false;
156 } 143 }
157 144
158 // Optional parameters. 145 // Optional parameters.
159 if (p2.isOptional) { 146 if (p2.isOptional) {
160 // If the base param is optional, the sub param must be optional: 147 // If the base param is optional, the sub param must be optional:
161 if (!p1.isOptional) return false; 148 if (!p1.isOptional) return false;
162 if (!p2.isNamed) { 149 if (!p2.isNamed) {
163 // either neither are named or 150 // either neither are named or
164 if (p1.isNamed) return false; 151 if (p1.isNamed) return false;
(...skipping 19 matching lines...) Expand all
184 bool _isClassSubType(ClassMirror m1, ClassMirror m2) { 171 bool _isClassSubType(ClassMirror m1, ClassMirror m2) {
185 // TODO(vsm): Consider some caching for efficiency here. 172 // TODO(vsm): Consider some caching for efficiency here.
186 173
187 // We support Dart's covariant generics with the caveat that we do not 174 // We support Dart's covariant generics with the caveat that we do not
188 // substitute bottom for dynamic in subtyping rules. 175 // substitute bottom for dynamic in subtyping rules.
189 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow: 176 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
190 // - S !<: S<T1, ..., Tn> 177 // - S !<: S<T1, ..., Tn>
191 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn> 178 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
192 if (m1 == m2) return true; 179 if (m1 == m2) return true;
193 180
194 if (m1.hasReflectedType && m1.reflectedType == Object) return false; 181 if (_isTop(m1)) return false;
195 182
196 // Check if m1 and m2 have the same raw type. If so, check covariance on 183 // Check if m1 and m2 have the same raw type. If so, check covariance on
197 // type parameters. 184 // type parameters.
198 if (m1.originalDeclaration == m2.originalDeclaration) { 185 if (m1.originalDeclaration == m2.originalDeclaration) {
186 if (_isRawClass(m2)) return true;
187 if (_isRawClass(m1)) return false;
188
199 final typeArguments1 = m1.typeArguments; 189 final typeArguments1 = m1.typeArguments;
200 final typeArguments2 = m2.typeArguments; 190 final typeArguments2 = m2.typeArguments;
201 final length = typeArguments1.length; 191 final length = typeArguments1.length;
202 if (typeArguments2.length == 0) { 192 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); 193 assert(typeArguments2.length == length);
210 for (var i = 0; i < length; ++i) { 194 for (var i = 0; i < length; ++i) {
211 var typeArgument1 = typeArguments1[i]; 195 var typeArgument1 = typeArguments1[i];
212 var typeArgument2 = typeArguments2[i]; 196 var typeArgument2 = typeArguments2[i];
213 if (!_isSubType(typeArgument1, typeArgument2)) { 197 if (!_isSubType(typeArgument1, typeArgument2)) {
214 return false; 198 return false;
215 } 199 }
216 } 200 }
217 return true; 201 return true;
218 } 202 }
219 203
220 // Check superclass. 204 // Check superclass.
221 if (_isClassSubType(m1.superclass, m2)) return true; 205 if (_isClassSubType(m1.superclass, m2)) return true;
222 206
207 // Check for mixins. The mixin getter returns the original class if there is
208 // no mixin.
209 if (m1 != m1.mixin && _isClassSubType(m1.mixin, m2)) return true;
210
223 // Check interfaces. 211 // Check interfaces.
224 for (final parent in m1.superinterfaces) { 212 for (final parent in m1.superinterfaces) {
225 if (_isClassSubType(parent, m2)) return true; 213 if (_isClassSubType(parent, m2)) return true;
226 } 214 }
227 215
228 return false; 216 return false;
229 } 217 }
230 218
219 final _dynamicMirror = reflectType(dynamic);
220 final _objectMirror = reflectType(Object);
221 final _nullMirror = reflectType(Null);
222
223 bool _isBottom(TypeMirror t, {bool dynamicIsBottom: false}) {
224 if (t == _dynamicMirror && dynamicIsBottom) return true;
225 // TODO(vsm): We need direct support for non-nullability in DartType.
226 // This should check on "true/nonnullable" Bottom
227 if (t == _nullMirror && _typeOptions.nonnullableTypes.isEmpty) return true;
Jennifer Messerly 2015/04/01 19:12:46 is this check needed? Normally isSubtype does not
vsm 2015/04/01 21:04:04 Yes, I'd been treating Null as bottom (as in the s
228 return false;
229 }
230
231 bool _isTop(TypeMirror t, {bool dynamicIsBottom: false}) {
232 if (t == _dynamicMirror && !dynamicIsBottom) return true;
233 if (t == _objectMirror) return true;
234 return false;
235 }
236
237 bool _isGroundTypeMirror(TypeMirror mirror) {
238 // Disallow generic type parameters.
239 if (mirror is TypeVariableMirror) return false;
Jennifer Messerly 2015/04/01 19:12:46 Does this happen at runtime? $ cat test.dart impo
vsm 2015/04/01 21:04:04 I think you are right. Changed this to an assert.
240
241 // Allow only 'raw' functions.
242 if (mirror is TypedefMirror) {
243 return _isRawFunction(mirror.referent);
244 }
245 if (mirror is FunctionTypeMirror) {
246 return _isRawFunction(mirror);
247 }
248
249 // Allow only 'raw' classes.
250 if (mirror is ClassMirror) {
251 return _isRawClass(mirror);
252 }
253
254 // Only dynamic should be left. Should this be allowed?
255 // It's not particularly useful.
256 assert(mirror.reflectedType == dynamic);
257 return true;
258 }
259
260 bool _isRawFunction(FunctionTypeMirror mirror) {
261 var returnType = mirror.returnType;
262 if (!_isTop(returnType)) return false;
263 for (var parameter in mirror.parameters) {
264 var paramType = parameter.type;
265 if (!_isBottom(paramType, dynamicIsBottom: true)) return false;
266 }
267 return true;
268 }
269
231 bool _isRawClass(ClassMirror mirror) { 270 bool _isRawClass(ClassMirror mirror) {
232 // Allow only raw types. 271 // Allow only raw types.
233 if (mirror == mirror.originalDeclaration) return true; 272 if (mirror == mirror.originalDeclaration) return true;
234 final dynamicMirror = reflectType(dynamic);
235 for (var typeArgument in mirror.typeArguments) { 273 for (var typeArgument in mirror.typeArguments) {
236 if (typeArgument != dynamicMirror) return false; 274 if (!_isTop(typeArgument)) return false;
237 } 275 }
238 return true; 276 return true;
239 } 277 }
240 278
241 TypeMirror _canonicalizeTypeMirror(TypeMirror t) { 279 TypeMirror _canonicalizeTypeMirror(TypeMirror t) {
242 if (t is TypedefMirror) { 280 if (t is TypedefMirror) {
243 // We canonicalize Typedefs to their underlying function types. 281 // We canonicalize Typedefs to their underlying function types.
244 t = (t as TypedefMirror).referent; 282 t = (t as TypedefMirror).referent;
245 } 283 }
246 if (t is ClassMirror && _isRawClass(t)) { 284 if (t is ClassMirror && _isRawClass(t)) {
247 // We canonicalize T<dynamic> to T. 285 // We canonicalize T<dynamic> to T.
248 t = t.originalDeclaration; 286 t = t.originalDeclaration;
249 } 287 }
250 return t; 288 return t;
251 } 289 }
252 290
253 bool _reflects(TypeMirror mirror, Type t) { 291 bool _reflects(TypeMirror mirror, Type t) {
254 return mirror.hasReflectedType && mirror.reflectedType == t; 292 return mirror.hasReflectedType && mirror.reflectedType == t;
255 } 293 }
256 294
257 bool _isSubType(TypeMirror t1, TypeMirror t2) { 295 bool _isSubType(TypeMirror t1, TypeMirror t2, {bool dynamicIsBottom: false}) {
258 t1 = _canonicalizeTypeMirror(t1); 296 t1 = _canonicalizeTypeMirror(t1);
259 t2 = _canonicalizeTypeMirror(t2); 297 t2 = _canonicalizeTypeMirror(t2);
260 298
299 if (t1 is TypeVariableMirror) {
Jennifer Messerly 2015/04/01 19:12:46 similar question about TypeVariableMirror, do we a
vsm 2015/04/01 21:04:04 I actually did hit this, in part because of how we
300 t1 = t1.upperBound;
301 }
302
303 if (t2 is TypeVariableMirror) {
304 // TODO(vsm): Bottom?
305 t2 = _nullMirror;
306 }
307
261 if (t1 == t2) return true; 308 if (t1 == t2) return true;
262 309
263 // In Dart, dynamic is effectively both top and bottom. 310 // Trivially true.
264 // Here, we treat dynamic as top - the base type of everything. 311 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
265 if (_reflects(t1, dynamic)) return false; 312 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
266 if (_reflects(t2, dynamic)) return true; 313 return true;
314 }
267 315
268 // Object only subtypes dynamic and Object. 316 // Trivially false.
269 if (_reflects(t2, Object)) return true; 317 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
270 if (_reflects(t1, Object)) return false; 318 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
319 return false;
320 }
321
322 // The null type is a subtype of any nonnullable type.
323 if (t1 == _nullMirror) {
324 // Return false iff t2 *may* be a primitive type.
325 return !isPrimitiveType(t2);
326 }
271 327
272 // "Traditional" name-based subtype check. 328 // "Traditional" name-based subtype check.
273 final c1 = t1 as ClassMirror; 329 final c1 = t1 as ClassMirror;
274 final c2 = t2 as ClassMirror; 330 final c2 = t2 as ClassMirror;
275 if (_isClassSubType(c1, c2)) { 331 if (_isClassSubType(c1, c2)) {
276 return true; 332 return true;
277 } 333 }
278 334
279 // Function subtyping. 335 // Function subtyping.
280 // Note: it appears under the hood all Dart functions map to a class / hidden type 336 // 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; 371 ret1 = call1.returnType;
316 params1 = call1.parameters; 372 params1 = call1.parameters;
317 } 373 }
318 374
319 // Any type that implements a call method implicitly subtypes Function. 375 // Any type that implements a call method implicitly subtypes Function.
320 if (_reflects(c2, Function)) return true; 376 if (_reflects(c2, Function)) return true;
321 377
322 // Check structural function subtyping 378 // Check structural function subtyping
323 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters); 379 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters);
324 } 380 }
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