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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/compile_time_constants.dart

Issue 146733003: Handle type checking of generic compile time constants. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add regression test. Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of dart2js; 5 part of dart2js;
6 6
7 /** 7 /**
8 * The [ConstantHandler] keeps track of compile-time constants, 8 * The [ConstantHandler] keeps track of compile-time constants,
9 * initializations of global and static fields, and default values of 9 * initializations of global and static fields, and default values of
10 * optional parameters. 10 * optional parameters.
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 compiler.resolver.resolveRedirectionChain(constructor, node); 714 compiler.resolver.resolveRedirectionChain(constructor, node);
715 InterfaceType constructedType = constructor.computeTargetType(type); 715 InterfaceType constructedType = constructor.computeTargetType(type);
716 constructor = constructor.redirectionTarget; 716 constructor = constructor.redirectionTarget;
717 ClassElement classElement = constructor.getEnclosingClass(); 717 ClassElement classElement = constructor.getEnclosingClass();
718 // The constructor must be an implementation to ensure that field 718 // The constructor must be an implementation to ensure that field
719 // initializers are handled correctly. 719 // initializers are handled correctly.
720 constructor = constructor.implementation; 720 constructor = constructor.implementation;
721 assert(invariant(node, constructor.isImplementation)); 721 assert(invariant(node, constructor.isImplementation));
722 722
723 List<Constant> arguments = getArguments(constructor); 723 List<Constant> arguments = getArguments(constructor);
724 ConstructorEvaluator evaluator = 724 ConstructorEvaluator evaluator = new ConstructorEvaluator(
725 new ConstructorEvaluator(constructor, handler, compiler); 725 constructedType, constructor, handler, compiler);
726 evaluator.evaluateConstructorFieldValues(arguments); 726 evaluator.evaluateConstructorFieldValues(arguments);
727 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); 727 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
728 728
729 return new ConstructedConstant(constructedType, jsNewArguments); 729 return new ConstructedConstant(constructedType, jsNewArguments);
730 } 730 }
731 731
732 Constant visitParenthesizedExpression(ParenthesizedExpression node) { 732 Constant visitParenthesizedExpression(ParenthesizedExpression node) {
733 return node.expression.accept(this); 733 return node.expression.accept(this);
734 } 734 }
735 735
(...skipping 25 matching lines...) Expand all
761 761
762 error(Node node) { 762 error(Node node) {
763 // Just fail without reporting it anywhere. 763 // Just fail without reporting it anywhere.
764 throw new CompileTimeConstantError( 764 throw new CompileTimeConstantError(
765 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const {}, 765 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const {},
766 compiler.terseDiagnostics); 766 compiler.terseDiagnostics);
767 } 767 }
768 } 768 }
769 769
770 class ConstructorEvaluator extends CompileTimeConstantEvaluator { 770 class ConstructorEvaluator extends CompileTimeConstantEvaluator {
771 final InterfaceType constructedType;
771 final FunctionElement constructor; 772 final FunctionElement constructor;
772 final Map<Element, Constant> definitions; 773 final Map<Element, Constant> definitions;
773 final Map<Element, Constant> fieldValues; 774 final Map<Element, Constant> fieldValues;
774 775
775 /** 776 /**
776 * Documentation wanted -- johnniwinther 777 * Documentation wanted -- johnniwinther
777 * 778 *
778 * Invariant: [constructor] must be an implementation element. 779 * Invariant: [constructor] must be an implementation element.
779 */ 780 */
780 ConstructorEvaluator(FunctionElement constructor, 781 ConstructorEvaluator(InterfaceType this.constructedType,
782 FunctionElement constructor,
781 ConstantHandler handler, 783 ConstantHandler handler,
782 Compiler compiler) 784 Compiler compiler)
783 : this.constructor = constructor, 785 : this.constructor = constructor,
784 this.definitions = new Map<Element, Constant>(), 786 this.definitions = new Map<Element, Constant>(),
785 this.fieldValues = new Map<Element, Constant>(), 787 this.fieldValues = new Map<Element, Constant>(),
786 super(handler, 788 super(handler,
787 compiler.resolver.resolveMethodElement(constructor.declaration), 789 compiler.resolver.resolveMethodElement(constructor.declaration),
788 compiler, 790 compiler,
789 isConst: true) { 791 isConst: true) {
790 assert(invariant(constructor, constructor.isImplementation)); 792 assert(invariant(constructor, constructor.isImplementation));
791 } 793 }
792 794
793 Constant visitSend(Send send) { 795 Constant visitSend(Send send) {
794 Element element = elements[send]; 796 Element element = elements[send];
795 if (Elements.isLocal(element)) { 797 if (Elements.isLocal(element)) {
796 Constant constant = definitions[element]; 798 Constant constant = definitions[element];
797 if (constant == null) { 799 if (constant == null) {
798 compiler.internalError("Local variable without value", node: send); 800 compiler.internalError("Local variable without value", node: send);
799 } 801 }
800 return constant; 802 return constant;
801 } 803 }
802 return super.visitSend(send); 804 return super.visitSend(send);
803 } 805 }
804 806
805 void potentiallyCheckType(Node node, Element element, Constant constant) { 807 void potentiallyCheckType(Node node,
karlklose 2014/01/29 10:44:23 'elementType' -> 'type'? I think the name of the
Johnni Winther 2014/01/30 08:25:23 Done.
808 DartType elementType,
809 Constant constant) {
806 if (compiler.enableTypeAssertions) { 810 if (compiler.enableTypeAssertions) {
807 DartType elementType = element.computeType(compiler);
808 DartType constantType = constant.computeType(compiler); 811 DartType constantType = constant.computeType(compiler);
809 // TODO(ngeoffray): Handle type parameters. 812 if (!compiler.types.isSubtype(constantType, elementType)) {
810 if (elementType.element.isTypeVariable()) return;
811 if (!constantSystem.isSubtype(compiler, constantType, elementType)) {
812 compiler.reportFatalError( 813 compiler.reportFatalError(
813 node, MessageKind.NOT_ASSIGNABLE.error, 814 node, MessageKind.NOT_ASSIGNABLE.error,
814 {'fromType': elementType, 'toType': constantType}); 815 {'fromType': constantType, 'toType': elementType});
815 } 816 }
816 } 817 }
817 } 818 }
818 819
819 void updateFieldValue(Node node, Element element, Constant constant) { 820 void updateFieldValue(Node node,
karlklose 2014/01/29 10:44:23 Still fits on one line.
Johnni Winther 2014/01/30 08:25:23 Done.
820 potentiallyCheckType(node, element, constant); 821 Element element,
822 Constant constant) {
823 DartType elementType =
824 element.computeType(compiler).substByContext(constructedType);
825 potentiallyCheckType(node, elementType, constant);
821 fieldValues[element] = constant; 826 fieldValues[element] = constant;
822 } 827 }
823 828
824 /** 829 /**
825 * Given the arguments (a list of constants) assigns them to the parameters, 830 * Given the arguments (a list of constants) assigns them to the parameters,
826 * updating the definitions map. If the constructor has field-initializer 831 * updating the definitions map. If the constructor has field-initializer
827 * parameters (like [:this.x:]), also updates the [fieldValues] map. 832 * parameters (like [:this.x:]), also updates the [fieldValues] map.
828 */ 833 */
829 void assignArgumentsToParameters(List<Constant> arguments) { 834 void assignArgumentsToParameters(List<Constant> arguments) {
830 // Assign arguments to parameters. 835 // Assign arguments to parameters.
831 FunctionSignature parameters = constructor.computeSignature(compiler); 836 FunctionSignature signature = constructor.computeSignature(compiler);
832 int index = 0; 837 int index = 0;
833 parameters.orderedForEachParameter((Element parameter) { 838 signature.orderedForEachParameter((Element parameter) {
839 DartType parameterType =
840 parameter.computeType(compiler).substByContext(constructedType);
834 Constant argument = arguments[index++]; 841 Constant argument = arguments[index++];
835 Node node = parameter.parseNode(compiler); 842 Node node = parameter.parseNode(compiler);
836 potentiallyCheckType(node, parameter, argument); 843 potentiallyCheckType(node, parameterType, argument);
837 definitions[parameter] = argument; 844 definitions[parameter] = argument;
838 if (parameter.kind == ElementKind.FIELD_PARAMETER) { 845 if (parameter.kind == ElementKind.FIELD_PARAMETER) {
839 FieldParameterElement fieldParameterElement = parameter; 846 FieldParameterElement fieldParameterElement = parameter;
840 updateFieldValue(node, fieldParameterElement.fieldElement, argument); 847 updateFieldValue(node, fieldParameterElement.fieldElement, argument);
841 } 848 }
842 }); 849 });
843 } 850 }
844 851
845 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments, 852 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments,
846 FunctionElement targetConstructor) { 853 FunctionElement targetConstructor) {
847 ConstructorEvaluator evaluator = new ConstructorEvaluator( 854 ConstructorEvaluator evaluator = new ConstructorEvaluator(
855 constructedType.asInstanceOf(targetConstructor.getEnclosingClass()),
848 targetConstructor, handler, compiler); 856 targetConstructor, handler, compiler);
849 evaluator.evaluateConstructorFieldValues(compiledArguments); 857 evaluator.evaluateConstructorFieldValues(compiledArguments);
850 // Copy over the fieldValues from the super/redirect-constructor. 858 // Copy over the fieldValues from the super/redirect-constructor.
851 // No need to go through [updateFieldValue] because the 859 // No need to go through [updateFieldValue] because the
852 // assignments have already been checked in checked mode. 860 // assignments have already been checked in checked mode.
853 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); 861 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value);
854 } 862 }
855 863
856 /** 864 /**
857 * Runs through the initializers of the given [constructor] and updates 865 * Runs through the initializers of the given [constructor] and updates
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 if (fieldValue == null) { 955 if (fieldValue == null) {
948 // Use the default value. 956 // Use the default value.
949 fieldValue = handler.compileConstant(field); 957 fieldValue = handler.compileConstant(field);
950 } 958 }
951 jsNewArguments.add(fieldValue); 959 jsNewArguments.add(fieldValue);
952 }, 960 },
953 includeSuperAndInjectedMembers: true); 961 includeSuperAndInjectedMembers: true);
954 return jsNewArguments; 962 return jsNewArguments;
955 } 963 }
956 } 964 }
OLDNEW
« no previous file with comments | « no previous file | tests/language/const_constructor2_test.dart » ('j') | tests/language/const_constructor2_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698