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

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 comment 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
217 bool _isBottom(TypeMirror t, {bool dynamicIsBottom: false}) {
218 if (t == _dynamicMirror && dynamicIsBottom) return true;
219 // TODO(vsm): Do we need an explicit representation of Bottom?
220 return false;
221 }
222
223 bool _isTop(TypeMirror t, {bool dynamicIsBottom: false}) {
224 if (t == _dynamicMirror && !dynamicIsBottom) return true;
225 if (t == _objectMirror) return true;
226 return false;
227 }
228
229 bool _isGroundTypeMirror(TypeMirror mirror) {
230 // This is a runtime type - we should not see type parameters here.
231 assert(mirror is! TypeVariableMirror);
232
233 // Allow only 'raw' functions.
234 if (mirror is TypedefMirror) {
235 return _isRawFunction(mirror.referent);
236 }
237 if (mirror is FunctionTypeMirror) {
238 return _isRawFunction(mirror);
239 }
240
241 // Allow only 'raw' classes.
242 if (mirror is ClassMirror) {
243 return _isRawClass(mirror);
244 }
245
246 // Only dynamic should be left. Should this be allowed?
247 // It's not particularly useful.
248 assert(mirror.reflectedType == dynamic);
249 return true;
250 }
251
252 bool _isRawFunction(FunctionTypeMirror mirror) {
253 var returnType = mirror.returnType;
254 if (!_isTop(returnType)) return false;
255 for (var parameter in mirror.parameters) {
256 var paramType = parameter.type;
257 if (!_isBottom(paramType, dynamicIsBottom: true)) return false;
258 }
259 return true;
260 }
261
231 bool _isRawClass(ClassMirror mirror) { 262 bool _isRawClass(ClassMirror mirror) {
232 // Allow only raw types. 263 // Allow only raw types.
233 if (mirror == mirror.originalDeclaration) return true; 264 if (mirror == mirror.originalDeclaration) return true;
234 final dynamicMirror = reflectType(dynamic);
235 for (var typeArgument in mirror.typeArguments) { 265 for (var typeArgument in mirror.typeArguments) {
236 if (typeArgument != dynamicMirror) return false; 266 if (!_isTop(typeArgument)) return false;
237 } 267 }
238 return true; 268 return true;
239 } 269 }
240 270
241 TypeMirror _canonicalizeTypeMirror(TypeMirror t) { 271 TypeMirror _canonicalizeTypeMirror(TypeMirror t) {
242 if (t is TypedefMirror) { 272 if (t is TypedefMirror) {
243 // We canonicalize Typedefs to their underlying function types. 273 // We canonicalize Typedefs to their underlying function types.
244 t = (t as TypedefMirror).referent; 274 t = (t as TypedefMirror).referent;
245 } 275 }
246 if (t is ClassMirror && _isRawClass(t)) { 276 if (t is ClassMirror && _isRawClass(t)) {
247 // We canonicalize T<dynamic> to T. 277 // We canonicalize T<dynamic> to T.
248 t = t.originalDeclaration; 278 t = t.originalDeclaration;
249 } 279 }
250 return t; 280 return t;
251 } 281 }
252 282
253 bool _reflects(TypeMirror mirror, Type t) { 283 bool _reflects(TypeMirror mirror, Type t) {
254 return mirror.hasReflectedType && mirror.reflectedType == t; 284 return mirror.hasReflectedType && mirror.reflectedType == t;
255 } 285 }
256 286
257 bool _isSubType(TypeMirror t1, TypeMirror t2) { 287 bool _isSubType(TypeMirror t1, TypeMirror t2, {bool dynamicIsBottom: false}) {
258 t1 = _canonicalizeTypeMirror(t1); 288 t1 = _canonicalizeTypeMirror(t1);
259 t2 = _canonicalizeTypeMirror(t2); 289 t2 = _canonicalizeTypeMirror(t2);
260 290
291 if (t1 is TypeVariableMirror) {
292 t1 = t1.upperBound;
293 }
294
261 if (t1 == t2) return true; 295 if (t1 == t2) return true;
262 296
263 // In Dart, dynamic is effectively both top and bottom. 297 // Trivially true.
264 // Here, we treat dynamic as top - the base type of everything. 298 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
265 if (_reflects(t1, dynamic)) return false; 299 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
266 if (_reflects(t2, dynamic)) return true; 300 return true;
301 }
267 302
268 // Object only subtypes dynamic and Object. 303 // Trivially false.
269 if (_reflects(t2, Object)) return true; 304 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
270 if (_reflects(t1, Object)) return false; 305 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
306 return false;
307 }
271 308
272 // "Traditional" name-based subtype check. 309 // "Traditional" name-based subtype check.
273 final c1 = t1 as ClassMirror; 310 final c1 = t1 as ClassMirror;
274 final c2 = t2 as ClassMirror; 311 final c2 = t2 as ClassMirror;
275 if (_isClassSubType(c1, c2)) { 312 if (_isClassSubType(c1, c2)) {
276 return true; 313 return true;
277 } 314 }
278 315
279 // Function subtyping. 316 // Function subtyping.
280 // Note: it appears under the hood all Dart functions map to a class / hidden type 317 // 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; 352 ret1 = call1.returnType;
316 params1 = call1.parameters; 353 params1 = call1.parameters;
317 } 354 }
318 355
319 // Any type that implements a call method implicitly subtypes Function. 356 // Any type that implements a call method implicitly subtypes Function.
320 if (_reflects(c2, Function)) return true; 357 if (_reflects(c2, Function)) return true;
321 358
322 // Check structural function subtyping 359 // Check structural function subtyping
323 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters); 360 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters);
324 } 361 }
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