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

Side by Side Diff: lib/src/checker/rules.dart

Issue 1056183002: Better error messages (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: 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 | lib/src/codegen/reify_coercions.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.src.checker.rules; 5 library dev_compiler.src.checker.rules;
6 6
7 import 'package:analyzer/src/generated/ast.dart'; 7 import 'package:analyzer/src/generated/ast.dart';
8 import 'package:analyzer/src/generated/element.dart'; 8 import 'package:analyzer/src/generated/element.dart';
9 import 'package:analyzer/src/generated/resolver.dart'; 9 import 'package:analyzer/src/generated/resolver.dart';
10 10
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 return Coercion.cast(fromT, toT); 486 return Coercion.cast(fromT, toT);
487 } 487 }
488 return Coercion.error(); 488 return Coercion.error();
489 } 489 }
490 490
491 StaticInfo checkAssignment(Expression expr, DartType toT, bool constContext) { 491 StaticInfo checkAssignment(Expression expr, DartType toT, bool constContext) {
492 final fromT = getStaticType(expr); 492 final fromT = getStaticType(expr);
493 final Coercion c = _coerceTo(fromT, toT, options.wrapClosures); 493 final Coercion c = _coerceTo(fromT, toT, options.wrapClosures);
494 if (c is Identity) return null; 494 if (c is Identity) return null;
495 if (c is CoercionError) return new StaticTypeError(this, expr, toT); 495 if (c is CoercionError) return new StaticTypeError(this, expr, toT);
496 if (options.inferDownwards && inferrer.inferExpression(expr, toT)) { 496 var reason = null;
497 return InferredType.create(this, expr, toT); 497 if (options.inferDownwards) {
498 var errors = <String>[];
499 var ok = inferrer.inferExpression(expr, toT, errors);
500 if (ok) return InferredType.create(this, expr, toT);
501 reason = (errors.isNotEmpty) ? errors.first : null;
498 } 502 }
499 if (constContext && !options.allowConstCasts) { 503 if (constContext && !options.allowConstCasts) {
500 return new StaticTypeError(this, expr, toT); 504 reason = (reason == null) ? "Cast not allowed in const context" : reason;
505 return new StaticTypeError(this, expr, toT, reason: reason);
501 } 506 }
502 if (c is Cast) return DownCast.create(this, expr, c); 507 if (c is Cast) return DownCast.create(this, expr, c, reason: reason);
503 if (c is Wrapper) return ClosureWrap.create(this, expr, c, toT); 508 if (c is Wrapper) return ClosureWrap.create(this, expr, c, toT);
504 assert(false); 509 assert(false);
505 return null; 510 return null;
506 } 511 }
507 512
508 DartType elementType(Element e) { 513 DartType elementType(Element e) {
509 return (e as dynamic).type; 514 return (e as dynamic).type;
510 } 515 }
511 516
512 bool isDynamic(DartType t) => options.ignoreTypes || t.isDynamic; 517 bool isDynamic(DartType t) => options.ignoreTypes || t.isDynamic;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 void annotateListLiteral(ListLiteral e, List<DartType> targs) {} 565 void annotateListLiteral(ListLiteral e, List<DartType> targs) {}
561 566
562 /// Called for each map literal which gets inferred 567 /// Called for each map literal which gets inferred
563 void annotateMapLiteral(MapLiteral e, List<DartType> targs) {} 568 void annotateMapLiteral(MapLiteral e, List<DartType> targs) {}
564 569
565 /// Called for each new/const which gets inferred 570 /// Called for each new/const which gets inferred
566 void annotateInstanceCreationExpression( 571 void annotateInstanceCreationExpression(
567 InstanceCreationExpression e, List<DartType> targs) {} 572 InstanceCreationExpression e, List<DartType> targs) {}
568 573
569 /// Downward inference 574 /// Downward inference
570 bool inferExpression(Expression e, DartType t) { 575 bool inferExpression(Expression e, DartType t, List<String> errors) {
571 if (e is Conversion) return inferExpression(e.node, t); 576 if (e is Conversion) return inferExpression(e.node, t, errors);
572 if (rules.isSubTypeOf(rules.getStaticType(e), t)) return true; 577 if (rules.isSubTypeOf(rules.getStaticType(e), t)) return true;
573 if (e is FunctionExpression) return _inferFunctionExpression(e, t); 578 if (e is FunctionExpression) return _inferFunctionExpression(e, t, errors);
574 if (e is ListLiteral) return _inferListLiteral(e, t); 579 if (e is ListLiteral) return _inferListLiteral(e, t, errors);
575 if (e is MapLiteral) return _inferMapLiteral(e, t); 580 if (e is MapLiteral) return _inferMapLiteral(e, t, errors);
576 if (e is NamedExpression) return _inferNamedExpression(e, t); 581 if (e is NamedExpression) return _inferNamedExpression(e, t, errors);
577 if (e is InstanceCreationExpression) return _inferInstanceCreationExpression ( 582 if (e is InstanceCreationExpression) return _inferInstanceCreationExpression (
578 e, t); 583 e, t, errors);
584 errors.add("$e cannot be typed as $t");
579 return false; 585 return false;
580 } 586 }
581 587
582 /// If t1 = I<dynamic, ..., dynamic>, then look for a supertype 588 /// If t1 = I<dynamic, ..., dynamic>, then look for a supertype
583 /// of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'> 589 /// of t1 of the form K<S0, ..., Sm> where t2 = K<S0', ..., Sm'>
584 /// If the supertype exists, use the constraints S0 <: S0', ... Sm <: Sm' 590 /// If the supertype exists, use the constraints S0 <: S0', ... Sm <: Sm'
585 /// to derive a concrete instantation for I of the form <T0, ..., Tn>, 591 /// to derive a concrete instantation for I of the form <T0, ..., Tn>,
586 /// such that I<T0, .., Tn> <: t2 592 /// such that I<T0, .., Tn> <: t2
587 List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) { 593 List<DartType> _matchTypes(InterfaceType t1, InterfaceType t2) {
588 if (t1 == t2) return t2.typeArguments; 594 if (t1 == t2) return t2.typeArguments;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 if (!match(t1.element.type)) return null; 660 if (!match(t1.element.type)) return null;
655 var newT1 = t1.element.type.substitute4(actuals); 661 var newT1 = t1.element.type.substitute4(actuals);
656 // If we found a solution, return it. 662 // If we found a solution, return it.
657 if (rules.isSubTypeOf(newT1, t2)) return actuals; 663 if (rules.isSubTypeOf(newT1, t2)) return actuals;
658 return null; 664 return null;
659 } 665 }
660 666
661 /// These assume that e is not already a subtype of t 667 /// These assume that e is not already a subtype of t
662 668
663 bool _inferInstanceCreationExpression( 669 bool _inferInstanceCreationExpression(
664 InstanceCreationExpression e, DartType t) { 670 InstanceCreationExpression e, DartType t, errors) {
665 var arguments = e.argumentList.arguments; 671 var arguments = e.argumentList.arguments;
666 var rawType = rules.getStaticType(e); 672 var rawType = rules.getStaticType(e);
667 // rawType is the instantiated type of the instance 673 // rawType is the instantiated type of the instance
668 if (rawType is! InterfaceType) return false; 674 if (rawType is! InterfaceType) return false;
669 var type = (rawType as InterfaceType); 675 var type = (rawType as InterfaceType);
670 if (type.typeParameters == null || 676 if (type.typeParameters == null ||
671 type.typeParameters.length == 0) return false; 677 type.typeParameters.length == 0) return false;
672 if (e.constructorName.type == null) return false; 678 if (e.constructorName.type == null) return false;
673 // classTypeName is the type name of the class being instantiated 679 // classTypeName is the type name of the class being instantiated
674 var classTypeName = e.constructorName.type; 680 var classTypeName = e.constructorName.type;
(...skipping 20 matching lines...) Expand all
695 var fType = baseType.substitute2(targs, tparams); 701 var fType = baseType.substitute2(targs, tparams);
696 { 702 {
697 var rTypes = fType.normalParameterTypes; 703 var rTypes = fType.normalParameterTypes;
698 var oTypes = fType.optionalParameterTypes; 704 var oTypes = fType.optionalParameterTypes;
699 var pTypes = new List.from(rTypes)..addAll(oTypes); 705 var pTypes = new List.from(rTypes)..addAll(oTypes);
700 var pArgs = arguments.where((x) => x is! NamedExpression); 706 var pArgs = arguments.where((x) => x is! NamedExpression);
701 var pi = 0; 707 var pi = 0;
702 for (var arg in pArgs) { 708 for (var arg in pArgs) {
703 if (pi >= pTypes.length) return false; 709 if (pi >= pTypes.length) return false;
704 var argType = pTypes[pi]; 710 var argType = pTypes[pi];
705 if (!inferExpression(arg, argType)) return false; 711 if (!inferExpression(arg, argType, errors)) return false;
706 pi++; 712 pi++;
707 } 713 }
708 var nTypes = fType.namedParameterTypes; 714 var nTypes = fType.namedParameterTypes;
709 for (var arg0 in arguments) { 715 for (var arg0 in arguments) {
710 if (arg0 is! NamedExpression) continue; 716 if (arg0 is! NamedExpression) continue;
711 var arg = arg0 as NamedExpression; 717 var arg = arg0 as NamedExpression;
712 SimpleIdentifier nameNode = arg.name.label; 718 SimpleIdentifier nameNode = arg.name.label;
713 String name = nameNode.name; 719 String name = nameNode.name;
714 var argType = nTypes[name]; 720 var argType = nTypes[name];
715 if (argType == null) return false; 721 if (argType == null) return false;
716 if (!inferExpression(arg, argType)) return false; 722 if (!inferExpression(arg, argType, errors)) return false;
717 } 723 }
718 } 724 }
719 annotateInstanceCreationExpression(e, targs); 725 annotateInstanceCreationExpression(e, targs);
720 return true; 726 return true;
721 } 727 }
722 728
723 bool _inferNamedExpression(NamedExpression e, DartType t) { 729 bool _inferNamedExpression(NamedExpression e, DartType t, errors) {
724 return inferExpression(e.expression, t); 730 return inferExpression(e.expression, t, errors);
725 } 731 }
726 732
727 bool _inferFunctionExpression(FunctionExpression e, DartType t) { 733 bool _inferFunctionExpression(FunctionExpression e, DartType t, errors) {
728 if (t is! FunctionType) return false; 734 if (t is! FunctionType) return false;
729 var returnT = (t as FunctionType).returnType; 735 var returnT = (t as FunctionType).returnType;
730 if (returnT.isDynamic) return false; 736 if (returnT.isDynamic) return false;
731 var eType = e.staticType; 737 var eType = e.staticType;
732 if (eType is! FunctionType) return false; 738 if (eType is! FunctionType) return false;
733 if (e.body is! ExpressionFunctionBody) return false; 739 if (e.body is! ExpressionFunctionBody) return false;
734 var body = (e.body as ExpressionFunctionBody).expression; 740 var body = (e.body as ExpressionFunctionBody).expression;
735 if (!inferExpression(body, returnT)) return false; 741 if (!inferExpression(body, returnT, errors)) return false;
736 // TODO(leafp): Try narrowing the argument types if possible 742 // TODO(leafp): Try narrowing the argument types if possible
737 // to get better code in the function body. This requires checking 743 // to get better code in the function body. This requires checking
738 // that the body is well-typed at the more specific type. 744 // that the body is well-typed at the more specific type.
739 var element = (e.element as ExecutableElementImpl); 745 var element = (e.element as ExecutableElementImpl);
740 var oldReturnT = element.returnType; 746 var oldReturnT = element.returnType;
741 element.returnType = returnT; 747 element.returnType = returnT;
742 // Work around dynamic as bottom for now by handling function literals 748 // Work around dynamic as bottom for now by handling function literals
743 // with dynamic arguments specially. We already know the body is typable 749 // with dynamic arguments specially. We already know the body is typable
744 // at the chosen type, and if all args are dynamic, then function must be 750 // at the chosen type, and if all args are dynamic, then function must be
745 // typeable. 751 // typeable.
746 if ((eType as FunctionType).parameters.every((x) => x.type.isDynamic)) { 752 if ((eType as FunctionType).parameters.every((x) => x.type.isDynamic)) {
747 return true; 753 return true;
748 } 754 }
749 if (rules.isSubTypeOf(e.staticType, t)) return true; 755 if (rules.isSubTypeOf(e.staticType, t)) return true;
750 element.returnType = oldReturnT; 756 element.returnType = oldReturnT;
751 return false; 757 return false;
752 } 758 }
753 759
754 bool _inferListLiteral(ListLiteral e, DartType t) { 760 bool _inferListLiteral(ListLiteral e, DartType t, errors) {
755 var dyn = rules.provider.dynamicType; 761 var dyn = rules.provider.dynamicType;
756 var listT = rules.provider.listType.substitute4([dyn]); 762 var listT = rules.provider.listType.substitute4([dyn]);
757 // List <: t (using dart rules) must be true 763 // List <: t (using dart rules) must be true
758 if (!listT.isSubtypeOf(t)) return false; 764 if (!listT.isSubtypeOf(t)) return false;
759 // The list literal must have no type arguments 765 // The list literal must have no type arguments
760 if (e.typeArguments != null) return false; 766 if (e.typeArguments != null) return false;
761 if (t is! InterfaceType) return false; 767 if (t is! InterfaceType) return false;
762 var targs = _matchTypes(listT, t); 768 var targs = _matchTypes(listT, t);
763 if (targs == null) return false; 769 if (targs == null) return false;
764 assert(targs.length == 1); 770 assert(targs.length == 1);
765 var etype = targs[0]; 771 var etype = targs[0];
766 assert(!etype.isDynamic); 772 assert(!etype.isDynamic);
767 var elements = e.elements; 773 var elements = e.elements;
768 var b = elements.every((e) => inferExpression(e, etype)); 774 var b = elements.every((e) => inferExpression(e, etype, errors));
769 if (b) annotateListLiteral(e, targs); 775 if (b) annotateListLiteral(e, targs);
770 return b; 776 return b;
771 } 777 }
772 778
773 bool _inferMapLiteral(MapLiteral e, DartType t) { 779 bool _inferMapLiteral(MapLiteral e, DartType t, errors) {
774 var dyn = rules.provider.dynamicType; 780 var dyn = rules.provider.dynamicType;
775 var mapT = rules.provider.mapType.substitute4([dyn, dyn]); 781 var mapT = rules.provider.mapType.substitute4([dyn, dyn]);
776 // Map <: t (using dart rules) must be true 782 // Map <: t (using dart rules) must be true
777 if (!mapT.isSubtypeOf(t)) return false; 783 if (!mapT.isSubtypeOf(t)) return false;
778 // The map literal must have no type arguments 784 // The map literal must have no type arguments
779 if (e.typeArguments != null) return false; 785 if (e.typeArguments != null) return false;
780 if (t is! InterfaceType) return false; 786 if (t is! InterfaceType) return false;
781 var targs = _matchTypes(mapT, t); 787 var targs = _matchTypes(mapT, t);
782 if (targs == null) return false; 788 if (targs == null) return false;
783 assert(targs.length == 2); 789 assert(targs.length == 2);
784 var kType = targs[0]; 790 var kType = targs[0];
785 var vType = targs[1]; 791 var vType = targs[1];
786 assert(!(kType.isDynamic && vType.isDynamic)); 792 assert(!(kType.isDynamic && vType.isDynamic));
787 var entries = e.entries; 793 var entries = e.entries;
788 bool inferEntry(MapLiteralEntry entry) { 794 bool inferEntry(MapLiteralEntry entry) {
789 return inferExpression(entry.key, kType) && 795 return inferExpression(entry.key, kType, errors) &&
790 inferExpression(entry.value, vType); 796 inferExpression(entry.value, vType, errors);
791 } 797 }
792 var b = entries.every(inferEntry); 798 var b = entries.every(inferEntry);
793 if (b) annotateMapLiteral(e, targs); 799 if (b) annotateMapLiteral(e, targs);
794 return b; 800 return b;
795 } 801 }
796 } 802 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/codegen/reify_coercions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698