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

Side by Side Diff: pkg/compiler/lib/src/compile_time_constants.dart

Issue 1182663008: Typecheck const classes in the context of the constructor call. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
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 library dart2js.compile_time_constant_evaluator; 5 library dart2js.compile_time_constant_evaluator;
6 6
7 import 'constant_system_dart.dart'; 7 import 'constant_system_dart.dart';
8 import 'constants/constant_system.dart'; 8 import 'constants/constant_system.dart';
9 import 'constants/expressions.dart'; 9 import 'constants/expressions.dart';
10 import 'constants/values.dart'; 10 import 'constants/values.dart';
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 @override 146 @override
147 ConstantValue getConstantValueForVariable(VariableElement element) { 147 ConstantValue getConstantValueForVariable(VariableElement element) {
148 return getConstantValue(initialVariableValues[element.declaration]); 148 return getConstantValue(initialVariableValues[element.declaration]);
149 } 149 }
150 150
151 @override 151 @override
152 ConstantExpression getConstantForVariable(VariableElement element) { 152 ConstantExpression getConstantForVariable(VariableElement element) {
153 return initialVariableValues[element.declaration]; 153 return initialVariableValues[element.declaration];
154 } 154 }
155 155
156 ConstantExpression compileConstant(VariableElement element) { 156 ConstantExpression compileConstant(VariableElement element,
157 return compileVariable(element, isConst: true); 157 {bool checkType: true}) {
Johnni Winther 2015/06/17 06:56:29 This method overrides ConstantCompiler.compileCons
Harry Terkelsen 2015/08/10 23:49:34 Done.
158 return compileVariable(element, isConst: true, checkType: checkType);
158 } 159 }
159 160
160 ConstantExpression compileVariable(VariableElement element, 161 ConstantExpression compileVariable(VariableElement element,
161 {bool isConst: false}) { 162 {bool isConst: false,
163 bool checkType: true}) {
Johnni Winther 2015/06/17 06:56:29 Ditto.
Harry Terkelsen 2015/08/10 23:49:34 Done.
162 164
163 if (initialVariableValues.containsKey(element.declaration)) { 165 if (initialVariableValues.containsKey(element.declaration)) {
164 ConstantExpression result = initialVariableValues[element.declaration]; 166 ConstantExpression result = initialVariableValues[element.declaration];
165 return result; 167 return result;
166 } 168 }
167 AstElement currentElement = element.analyzableElement; 169 AstElement currentElement = element.analyzableElement;
168 return compiler.withCurrentElement(currentElement, () { 170 return compiler.withCurrentElement(currentElement, () {
169 // TODO(johnniwinther): Avoid this eager analysis. 171 // TODO(johnniwinther): Avoid this eager analysis.
170 _analyzeElementEagerly(compiler, currentElement); 172 _analyzeElementEagerly(compiler, currentElement);
171 173
172 ConstantExpression constant = compileVariableWithDefinitions( 174 ConstantExpression constant = compileVariableWithDefinitions(
173 element, currentElement.resolvedAst.elements, isConst: isConst); 175 element, currentElement.resolvedAst.elements, isConst: isConst,
176 checkType: checkType);
174 return constant; 177 return constant;
175 }); 178 });
176 } 179 }
177 180
178 /** 181 /**
179 * Returns the a compile-time constant if the variable could be compiled 182 * Returns the a compile-time constant if the variable could be compiled
180 * eagerly. If the variable needs to be initialized lazily returns `null`. 183 * eagerly. If the variable needs to be initialized lazily returns `null`.
181 * If the variable is `const` but cannot be compiled eagerly reports an 184 * If the variable is `const` but cannot be compiled eagerly reports an
182 * error. 185 * error.
183 */ 186 */
184 ConstantExpression compileVariableWithDefinitions(VariableElement element, 187 ConstantExpression compileVariableWithDefinitions(VariableElement element,
185 TreeElements definitions, 188 TreeElements definitions,
186 {bool isConst: false}) { 189 {bool isConst: false,
190 bool checkType: true}) {
187 Node node = element.node; 191 Node node = element.node;
188 if (pendingVariables.contains(element)) { 192 if (pendingVariables.contains(element)) {
189 if (isConst) { 193 if (isConst) {
190 compiler.reportError( 194 compiler.reportError(
191 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); 195 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
192 ConstantExpression expression = new ErroneousConstantExpression(); 196 ConstantExpression expression = new ErroneousConstantExpression();
193 constantValueMap[expression] = constantSystem.createNull(); 197 constantValueMap[expression] = constantSystem.createNull();
194 return expression; 198 return expression;
195 } 199 }
196 return null; 200 return null;
197 } 201 }
198 pendingVariables.add(element); 202 pendingVariables.add(element);
199 203
200 Expression initializer = element.initializer; 204 Expression initializer = element.initializer;
201 ConstantExpression expression; 205 ConstantExpression expression;
202 if (initializer == null) { 206 if (initializer == null) {
203 // No initial value. 207 // No initial value.
204 expression = new NullConstantExpression(); 208 expression = new NullConstantExpression();
205 constantValueMap[expression] = constantSystem.createNull(); 209 constantValueMap[expression] = constantSystem.createNull();
206 } else { 210 } else {
207 expression = compileNodeWithDefinitions( 211 expression = compileNodeWithDefinitions(
208 initializer, definitions, isConst: isConst); 212 initializer, definitions, isConst: isConst);
209 if (compiler.enableTypeAssertions && 213 if (compiler.enableTypeAssertions &&
214 checkType &&
210 expression != null && 215 expression != null &&
211 element.isField) { 216 element.isField) {
212 DartType elementType = element.type; 217 DartType elementType = element.type;
213 ConstantValue value = getConstantValue(expression); 218 ConstantValue value = getConstantValue(expression);
214 if (elementType.isMalformed && !value.isNull) { 219 if (elementType.isMalformed && !value.isNull) {
215 if (isConst) { 220 if (isConst) {
216 ErroneousElement element = elementType.element; 221 ErroneousElement element = elementType.element;
217 compiler.reportError( 222 compiler.reportError(
218 node, element.messageKind, element.messageArguments); 223 node, element.messageKind, element.messageArguments);
219 } else { 224 } else {
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 if (Elements.isLocal(element)) { 1119 if (Elements.isLocal(element)) {
1115 AstConstant constant = definitions[element]; 1120 AstConstant constant = definitions[element];
1116 if (constant == null) { 1121 if (constant == null) {
1117 compiler.internalError(send, "Local variable without value."); 1122 compiler.internalError(send, "Local variable without value.");
1118 } 1123 }
1119 return constant; 1124 return constant;
1120 } 1125 }
1121 return super.visitSend(send); 1126 return super.visitSend(send);
1122 } 1127 }
1123 1128
1124 void potentiallyCheckType(Node node, 1129 void potentiallyCheckType(TypedElement element,
1125 TypedElement element,
1126 AstConstant constant) { 1130 AstConstant constant) {
1127 if (compiler.enableTypeAssertions) { 1131 if (compiler.enableTypeAssertions) {
1128 DartType elementType = element.type.substByContext(constructedType); 1132 DartType elementType = element.type.substByContext(constructedType);
1129 DartType constantType = constant.value.getType(compiler.coreTypes); 1133 DartType constantType = constant.value.getType(compiler.coreTypes);
1130 if (!constantSystem.isSubtype(compiler.types, 1134 if (!constantSystem.isSubtype(compiler.types,
1131 constantType, elementType)) { 1135 constantType, elementType)) {
1132 compiler.withCurrentElement(constant.element, () { 1136 compiler.withCurrentElement(constant.element, () {
1133 compiler.reportError( 1137 compiler.reportError(
1134 constant.node, MessageKind.NOT_ASSIGNABLE, 1138 constant.node, MessageKind.NOT_ASSIGNABLE,
1135 {'fromType': constantType, 'toType': elementType}); 1139 {'fromType': constantType, 'toType': elementType});
1136 }); 1140 });
1137 } 1141 }
1138 } 1142 }
1139 } 1143 }
1140 1144
1141 void updateFieldValue(Node node, 1145 void updateFieldValue(Node node,
1142 TypedElement element, 1146 TypedElement element,
1143 AstConstant constant) { 1147 AstConstant constant) {
1144 potentiallyCheckType(node, element, constant); 1148 potentiallyCheckType(element, constant);
1145 fieldValues[element] = constant; 1149 fieldValues[element] = constant;
1146 } 1150 }
1147 1151
1148 /** 1152 /**
1149 * Given the arguments (a list of constants) assigns them to the parameters, 1153 * Given the arguments (a list of constants) assigns them to the parameters,
1150 * updating the definitions map. If the constructor has field-initializer 1154 * updating the definitions map. If the constructor has field-initializer
1151 * parameters (like [:this.x:]), also updates the [fieldValues] map. 1155 * parameters (like [:this.x:]), also updates the [fieldValues] map.
1152 */ 1156 */
1153 void assignArgumentsToParameters(List<AstConstant> arguments) { 1157 void assignArgumentsToParameters(List<AstConstant> arguments) {
1154 if (constructor.isErroneous) return; 1158 if (constructor.isErroneous) return;
1155 // Assign arguments to parameters. 1159 // Assign arguments to parameters.
1156 FunctionSignature signature = constructor.functionSignature; 1160 FunctionSignature signature = constructor.functionSignature;
1157 int index = 0; 1161 int index = 0;
1158 signature.orderedForEachParameter((ParameterElement parameter) { 1162 signature.orderedForEachParameter((ParameterElement parameter) {
1159 AstConstant argument = arguments[index++]; 1163 AstConstant argument = arguments[index++];
1160 Node node = parameter.node; 1164 Node node = parameter.node;
1161 if (parameter.isInitializingFormal) { 1165 if (parameter.isInitializingFormal) {
1162 InitializingFormalElement initializingFormal = parameter; 1166 InitializingFormalElement initializingFormal = parameter;
1163 updateFieldValue(node, initializingFormal.fieldElement, argument); 1167 updateFieldValue(node, initializingFormal.fieldElement, argument);
1164 } else { 1168 } else {
1165 potentiallyCheckType(node, parameter, argument); 1169 potentiallyCheckType(parameter, argument);
1166 definitions[parameter] = argument; 1170 definitions[parameter] = argument;
1167 } 1171 }
1168 }); 1172 });
1169 } 1173 }
1170 1174
1171 void evaluateSuperOrRedirectSend(List<AstConstant> compiledArguments, 1175 void evaluateSuperOrRedirectSend(List<AstConstant> compiledArguments,
1172 FunctionElement targetConstructor) { 1176 FunctionElement targetConstructor) {
1173 ConstructorEvaluator evaluator = new ConstructorEvaluator( 1177 ConstructorEvaluator evaluator = new ConstructorEvaluator(
1174 constructedType.asInstanceOf(targetConstructor.enclosingClass), 1178 constructedType.asInstanceOf(targetConstructor.enclosingClass),
1175 targetConstructor, handler, compiler); 1179 targetConstructor, handler, compiler);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 /// inheritance chain of [classElement]. 1276 /// inheritance chain of [classElement].
1273 Map<FieldElement, AstConstant> buildFieldConstants( 1277 Map<FieldElement, AstConstant> buildFieldConstants(
1274 ClassElement classElement) { 1278 ClassElement classElement) {
1275 Map<FieldElement, AstConstant> fieldConstants = 1279 Map<FieldElement, AstConstant> fieldConstants =
1276 <FieldElement, AstConstant>{}; 1280 <FieldElement, AstConstant>{};
1277 classElement.implementation.forEachInstanceField( 1281 classElement.implementation.forEachInstanceField(
1278 (ClassElement enclosing, FieldElement field) { 1282 (ClassElement enclosing, FieldElement field) {
1279 AstConstant fieldValue = fieldValues[field]; 1283 AstConstant fieldValue = fieldValues[field];
1280 if (fieldValue == null) { 1284 if (fieldValue == null) {
1281 // Use the default value. 1285 // Use the default value.
1282 ConstantExpression fieldExpression = handler.compileConstant(field); 1286 ConstantExpression fieldExpression =
1287 handler.compileConstant(field, checkType: false);
1283 fieldValue = new AstConstant.fromDefaultValue( 1288 fieldValue = new AstConstant.fromDefaultValue(
1284 field, 1289 field,
1285 fieldExpression, 1290 fieldExpression,
1286 handler.getConstantValue(fieldExpression)); 1291 handler.getConstantValue(fieldExpression));
1292 potentiallyCheckType(field, fieldValue);
1287 } 1293 }
1288 fieldConstants[field] = fieldValue; 1294 fieldConstants[field] = fieldValue;
1289 }, 1295 },
1290 includeSuperAndInjectedMembers: true); 1296 includeSuperAndInjectedMembers: true);
1291 return fieldConstants; 1297 return fieldConstants;
1292 } 1298 }
1293 } 1299 }
1294 1300
1295 /// A constant created from the front-end AST. 1301 /// A constant created from the front-end AST.
1296 /// 1302 ///
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 // TODO(johnniwinther): Return a [NonConstantValue] instead. 1336 // TODO(johnniwinther): Return a [NonConstantValue] instead.
1331 new ErroneousConstantExpression(), new NullConstantValue()); 1337 new ErroneousConstantExpression(), new NullConstantValue());
1332 } 1338 }
1333 1339
1334 // TODO(johnniwinther): Avoid the need for this hack. 1340 // TODO(johnniwinther): Avoid the need for this hack.
1335 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { 1341 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) {
1336 WorldImpact worldImpact = compiler.analyzeElement(element.declaration); 1342 WorldImpact worldImpact = compiler.analyzeElement(element.declaration);
1337 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact); 1343 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact);
1338 return element.resolvedAst.elements; 1344 return element.resolvedAst.elements;
1339 } 1345 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698