OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.type_algebra; | 4 library kernel.type_algebra; |
5 | 5 |
6 import 'ast.dart'; | 6 import 'ast.dart'; |
7 | 7 |
8 /// Returns a type where all occurrences of the given type parameters have been | 8 /// Returns a type where all occurrences of the given type parameters have been |
9 /// replaced with the corresponding types. | 9 /// replaced with the corresponding types. |
10 /// | 10 /// |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 } | 318 } |
319 | 319 |
320 Supertype visitSupertype(Supertype node) { | 320 Supertype visitSupertype(Supertype node) { |
321 if (node.typeArguments.isEmpty) return node; | 321 if (node.typeArguments.isEmpty) return node; |
322 int before = useCounter; | 322 int before = useCounter; |
323 var typeArguments = node.typeArguments.map(visit).toList(); | 323 var typeArguments = node.typeArguments.map(visit).toList(); |
324 if (useCounter == before) return node; | 324 if (useCounter == before) return node; |
325 return new Supertype(node.classNode, typeArguments); | 325 return new Supertype(node.classNode, typeArguments); |
326 } | 326 } |
327 | 327 |
| 328 NamedType visitNamedType(NamedType node) { |
| 329 int before = useCounter; |
| 330 var type = visit(node.type); |
| 331 if (useCounter == before) return node; |
| 332 return new NamedType(node.name, type); |
| 333 } |
| 334 |
328 DartType visit(DartType node) => node.accept(this); | 335 DartType visit(DartType node) => node.accept(this); |
329 | 336 |
330 DartType visitInvalidType(InvalidType node) => node; | 337 DartType visitInvalidType(InvalidType node) => node; |
331 DartType visitDynamicType(DynamicType node) => node; | 338 DartType visitDynamicType(DynamicType node) => node; |
332 DartType visitVoidType(VoidType node) => node; | 339 DartType visitVoidType(VoidType node) => node; |
333 DartType visitBottomType(BottomType node) => node; | 340 DartType visitBottomType(BottomType node) => node; |
334 | 341 |
335 DartType visitInterfaceType(InterfaceType node) { | 342 DartType visitInterfaceType(InterfaceType node) { |
336 if (node.typeArguments.isEmpty) return node; | 343 if (node.typeArguments.isEmpty) return node; |
337 int before = useCounter; | 344 int before = useCounter; |
(...skipping 23 matching lines...) Expand all Loading... |
361 // environment has been used inside the function. | 368 // environment has been used inside the function. |
362 var inner = node.typeParameters.isEmpty ? this : newInnerEnvironment(); | 369 var inner = node.typeParameters.isEmpty ? this : newInnerEnvironment(); |
363 int before = this.useCounter; | 370 int before = this.useCounter; |
364 // Invert the variance when translating parameters. | 371 // Invert the variance when translating parameters. |
365 inner.invertVariance(); | 372 inner.invertVariance(); |
366 var typeParameters = inner.freshTypeParameters(node.typeParameters); | 373 var typeParameters = inner.freshTypeParameters(node.typeParameters); |
367 var positionalParameters = node.positionalParameters.isEmpty | 374 var positionalParameters = node.positionalParameters.isEmpty |
368 ? const <DartType>[] | 375 ? const <DartType>[] |
369 : node.positionalParameters.map(inner.visit).toList(); | 376 : node.positionalParameters.map(inner.visit).toList(); |
370 var namedParameters = node.namedParameters.isEmpty | 377 var namedParameters = node.namedParameters.isEmpty |
371 ? const <String, DartType>{} | 378 ? const <NamedType>[] |
372 : _mapValues(node.namedParameters, inner.visit); | 379 : node.namedParameters.map(inner.visitNamedType).toList(); |
373 inner.invertVariance(); | 380 inner.invertVariance(); |
374 var returnType = inner.visit(node.returnType); | 381 var returnType = inner.visit(node.returnType); |
375 if (this.useCounter == before) return node; | 382 if (this.useCounter == before) return node; |
376 return new FunctionType(positionalParameters, returnType, | 383 return new FunctionType(positionalParameters, returnType, |
377 namedParameters: namedParameters, | 384 namedParameters: namedParameters, |
378 typeParameters: typeParameters, | 385 typeParameters: typeParameters, |
379 requiredParameterCount: node.requiredParameterCount); | 386 requiredParameterCount: node.requiredParameterCount); |
380 } | 387 } |
381 | 388 |
382 void bumpCountersUntil(_TypeSubstitutor target) { | 389 void bumpCountersUntil(_TypeSubstitutor target) { |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 for (int i = 0; i < type1.typeParameters.length; ++i) { | 552 for (int i = 0; i < type1.typeParameters.length; ++i) { |
546 var left = substitute(type1.typeParameters[i].bound, leftInstance); | 553 var left = substitute(type1.typeParameters[i].bound, leftInstance); |
547 var right = substitute(type2.typeParameters[i].bound, rightInstance); | 554 var right = substitute(type2.typeParameters[i].bound, rightInstance); |
548 if (!_unify(left, right)) return false; | 555 if (!_unify(left, right)) return false; |
549 } | 556 } |
550 for (int i = 0; i < type1.positionalParameters.length; ++i) { | 557 for (int i = 0; i < type1.positionalParameters.length; ++i) { |
551 var left = substitute(type1.positionalParameters[i], leftInstance); | 558 var left = substitute(type1.positionalParameters[i], leftInstance); |
552 var right = substitute(type2.positionalParameters[i], rightInstance); | 559 var right = substitute(type2.positionalParameters[i], rightInstance); |
553 if (!_unify(left, right)) return false; | 560 if (!_unify(left, right)) return false; |
554 } | 561 } |
555 for (var name in type1.namedParameters.keys) { | 562 for (int i = 0; i < type1.namedParameters.length; ++i) { |
556 var right = type2.namedParameters[name]; | 563 if (type1.namedParameters[i].name != type2.namedParameters[i].name) { |
557 if (right == null) return _fail(); | 564 return false; |
558 right = substitute(right, rightInstance); | 565 } |
559 var left = substitute(type1.namedParameters[name], leftInstance); | 566 var left = substitute(type1.namedParameters[i].type, leftInstance); |
| 567 var right = substitute(type2.namedParameters[i].type, rightInstance); |
560 if (!_unify(left, right)) return false; | 568 if (!_unify(left, right)) return false; |
561 } | 569 } |
562 var leftReturn = substitute(type1.returnType, leftInstance); | 570 var leftReturn = substitute(type1.returnType, leftInstance); |
563 var rightReturn = substitute(type2.returnType, rightInstance); | 571 var rightReturn = substitute(type2.returnType, rightInstance); |
564 if (!_unify(leftReturn, rightReturn)) return false; | 572 if (!_unify(leftReturn, rightReturn)) return false; |
565 return true; | 573 return true; |
566 } | 574 } |
567 if (type1 is TypeParameterType && | 575 if (type1 is TypeParameterType && |
568 type2 is TypeParameterType && | 576 type2 is TypeParameterType && |
569 type1.parameter == type2.parameter) { | 577 type1.parameter == type2.parameter) { |
(...skipping 28 matching lines...) Expand all Loading... |
598 } | 606 } |
599 } | 607 } |
600 | 608 |
601 class _OccurrenceVisitor extends DartTypeVisitor<bool> { | 609 class _OccurrenceVisitor extends DartTypeVisitor<bool> { |
602 final Set<TypeParameter> variables; | 610 final Set<TypeParameter> variables; |
603 | 611 |
604 _OccurrenceVisitor(this.variables); | 612 _OccurrenceVisitor(this.variables); |
605 | 613 |
606 bool visit(DartType node) => node.accept(this); | 614 bool visit(DartType node) => node.accept(this); |
607 | 615 |
| 616 bool visitNamedType(NamedType node) { |
| 617 return visit(node.type); |
| 618 } |
| 619 |
608 bool visitInvalidType(InvalidType node) => false; | 620 bool visitInvalidType(InvalidType node) => false; |
609 bool visitDynamicType(DynamicType node) => false; | 621 bool visitDynamicType(DynamicType node) => false; |
610 bool visitVoidType(VoidType node) => false; | 622 bool visitVoidType(VoidType node) => false; |
611 | 623 |
612 bool visitInterfaceType(InterfaceType node) { | 624 bool visitInterfaceType(InterfaceType node) { |
613 return node.typeArguments.any(visit); | 625 return node.typeArguments.any(visit); |
614 } | 626 } |
615 | 627 |
616 bool visitFunctionType(FunctionType node) { | 628 bool visitFunctionType(FunctionType node) { |
617 return node.typeParameters.any(handleTypeParameter) || | 629 return node.typeParameters.any(handleTypeParameter) || |
618 node.positionalParameters.any(visit) || | 630 node.positionalParameters.any(visit) || |
619 node.namedParameters.values.any(visit) || | 631 node.namedParameters.any(visitNamedType) || |
620 visit(node.returnType); | 632 visit(node.returnType); |
621 } | 633 } |
622 | 634 |
623 bool visitTypeParameterType(TypeParameterType node) { | 635 bool visitTypeParameterType(TypeParameterType node) { |
624 return variables == null || variables.contains(node.parameter); | 636 return variables == null || variables.contains(node.parameter); |
625 } | 637 } |
626 | 638 |
627 bool handleTypeParameter(TypeParameter node) { | 639 bool handleTypeParameter(TypeParameter node) { |
628 assert(!variables.contains(node)); | 640 assert(!variables.contains(node)); |
629 return node.bound.accept(this); | 641 return node.bound.accept(this); |
630 } | 642 } |
631 } | 643 } |
632 | 644 |
633 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( | 645 Map<dynamic/*=K*/, dynamic/*=W*/ > _mapValues/*<K,V,W>*/( |
634 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { | 646 Map<dynamic/*=K*/, dynamic/*=V*/ > map, dynamic/*=W*/ fn(dynamic/*=V*/)) { |
635 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; | 647 Map<dynamic/*=K*/, dynamic/*=W*/ > result = {}; |
636 map.forEach((key, value) { | 648 map.forEach((key, value) { |
637 result[key] = fn(value); | 649 result[key] = fn(value); |
638 }); | 650 }); |
639 return result; | 651 return result; |
640 } | 652 } |
OLD | NEW |