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

Side by Side Diff: pkg/analyzer/lib/src/generated/constant.dart

Issue 1167413005: In constant evaluation, consistently handle const depending on non-const. (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
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/all_the_rest_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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.constant; 8 library engine.constant;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 RecordingErrorListener errorListener = new RecordingErrorListener(); 322 RecordingErrorListener errorListener = new RecordingErrorListener();
323 ErrorReporter errorReporter = 323 ErrorReporter errorReporter =
324 new ErrorReporter(errorListener, constant.source); 324 new ErrorReporter(errorListener, constant.source);
325 DartObjectImpl dartObject = 325 DartObjectImpl dartObject =
326 defaultValue.accept(new ConstantVisitor(this, errorReporter)); 326 defaultValue.accept(new ConstantVisitor(this, errorReporter));
327 (constant as ParameterElementImpl).evaluationResult = 327 (constant as ParameterElementImpl).evaluationResult =
328 new EvaluationResultImpl(dartObject, errorListener.errors); 328 new EvaluationResultImpl(dartObject, errorListener.errors);
329 } 329 }
330 } 330 }
331 } else if (constant is VariableElement) { 331 } else if (constant is VariableElement) {
332 RecordingErrorListener errorListener = new RecordingErrorListener(); 332 Expression constantInitializer =
333 ErrorReporter errorReporter = 333 (constant as PotentiallyConstVariableElement).constantInitializer;
334 new ErrorReporter(errorListener, constant.source); 334 if (constantInitializer != null) {
335 DartObjectImpl dartObject = 335 RecordingErrorListener errorListener = new RecordingErrorListener();
336 (constant as PotentiallyConstVariableElement).constantInitializer 336 ErrorReporter errorReporter =
337 .accept(new ConstantVisitor(this, errorReporter)); 337 new ErrorReporter(errorListener, constant.source);
338 // Only check the type for truly const declarations (don't check final 338 DartObjectImpl dartObject = constantInitializer
339 // fields with initializers, since their types may be generic. The type 339 .accept(new ConstantVisitor(this, errorReporter));
340 // of the final field will be checked later, when the constructor is 340 // Only check the type for truly const declarations (don't check final
341 // invoked). 341 // fields with initializers, since their types may be generic. The type
342 if (dartObject != null && constant.isConst) { 342 // of the final field will be checked later, when the constructor is
343 if (!runtimeTypeMatch(dartObject, constant.type)) { 343 // invoked).
344 errorReporter.reportErrorForElement( 344 if (dartObject != null && constant.isConst) {
345 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, constant, 345 if (!runtimeTypeMatch(dartObject, constant.type)) {
346 [dartObject.type, constant.type]); 346 errorReporter.reportErrorForElement(
347 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
348 constant, [dartObject.type, constant.type]);
349 }
347 } 350 }
351 (constant as VariableElementImpl).evaluationResult =
352 new EvaluationResultImpl(dartObject, errorListener.errors);
348 } 353 }
349 (constant as VariableElementImpl).evaluationResult =
350 new EvaluationResultImpl(dartObject, errorListener.errors);
351 } else if (constant is ConstructorElement) { 354 } else if (constant is ConstructorElement) {
352 // No evaluation needs to be done; constructor declarations are only in 355 if (constant.isConst) {
353 // the dependency graph to ensure that any constants referred to in 356 // No evaluation needs to be done; constructor declarations are only in
354 // initializer lists and parameter defaults are evaluated before 357 // the dependency graph to ensure that any constants referred to in
355 // invocations of the constructor. However we do need to annotate the 358 // initializer lists and parameter defaults are evaluated before
356 // element as being free of constant evaluation cycles so that later code 359 // invocations of the constructor. However we do need to annotate the
357 // will know that it is safe to evaluate. 360 // element as being free of constant evaluation cycles so that later
358 (constant as ConstructorElementImpl).isCycleFree = true; 361 // code will know that it is safe to evaluate.
362 (constant as ConstructorElementImpl).isCycleFree = true;
363 }
359 } else if (constant is ConstantEvaluationTarget_Annotation) { 364 } else if (constant is ConstantEvaluationTarget_Annotation) {
360 Annotation constNode = constant.annotation; 365 Annotation constNode = constant.annotation;
361 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 366 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
362 // elementAnnotation is null if the annotation couldn't be resolved, in 367 // elementAnnotation is null if the annotation couldn't be resolved, in
363 // which case we skip it. 368 // which case we skip it.
364 if (elementAnnotation != null) { 369 if (elementAnnotation != null) {
365 Element element = elementAnnotation.element; 370 Element element = elementAnnotation.element;
366 if (element is PropertyAccessorElement && 371 if (element is PropertyAccessorElement &&
367 element.variable is VariableElementImpl) { 372 element.variable is VariableElementImpl) {
368 // The annotation is a reference to a compile-time constant variable. 373 // The annotation is a reference to a compile-time constant variable.
369 // Just copy the evaluation result. 374 // Just copy the evaluation result.
370 VariableElementImpl variableElement = 375 VariableElementImpl variableElement =
371 element.variable as VariableElementImpl; 376 element.variable as VariableElementImpl;
372 elementAnnotation.evaluationResult = variableElement.evaluationResult; 377 if (variableElement.evaluationResult != null) {
378 elementAnnotation.evaluationResult =
379 variableElement.evaluationResult;
380 } else {
381 // This could happen in the event that the annotation refers to a
382 // non-constant. The error is detected elsewhere, so just silently
383 // ignore it here.
384 elementAnnotation.evaluationResult = new EvaluationResultImpl(null);
385 }
373 } else if (element is ConstructorElementImpl && 386 } else if (element is ConstructorElementImpl &&
374 element.isConst && 387 element.isConst &&
375 constNode.arguments != null) { 388 constNode.arguments != null) {
376 RecordingErrorListener errorListener = new RecordingErrorListener(); 389 RecordingErrorListener errorListener = new RecordingErrorListener();
377 CompilationUnit sourceCompilationUnit = 390 CompilationUnit sourceCompilationUnit =
378 constNode.getAncestor((node) => node is CompilationUnit); 391 constNode.getAncestor((node) => node is CompilationUnit);
379 ErrorReporter errorReporter = new ErrorReporter( 392 ErrorReporter errorReporter = new ErrorReporter(
380 errorListener, sourceCompilationUnit.element.source); 393 errorListener, sourceCompilationUnit.element.source);
381 ConstantVisitor constantVisitor = 394 ConstantVisitor constantVisitor =
382 new ConstantVisitor(this, errorReporter); 395 new ConstantVisitor(this, errorReporter);
(...skipping 15 matching lines...) Expand all
398 AnalysisEngine.instance.logger.logError( 411 AnalysisEngine.instance.logger.logError(
399 "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}"); 412 "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
400 return; 413 return;
401 } 414 }
402 } 415 }
403 416
404 /** 417 /**
405 * Determine which constant elements need to have their values computed 418 * Determine which constant elements need to have their values computed
406 * prior to computing the value of [constant], and report them using 419 * prior to computing the value of [constant], and report them using
407 * [callback]. 420 * [callback].
421 *
422 * Note that it's possible (in erroneous code) for a constant to depend on a
423 * non-constant. When this happens, we report the dependency anyhow so that
424 * if the non-constant changes to a constant, we will know to recompute the
425 * thing that depends on it. [computeDependencies] and
426 * [computeConstantValue] are responsible for ignoring the request if they
427 * are asked to act on a non-constant target.
408 */ 428 */
409 void computeDependencies( 429 void computeDependencies(
410 ConstantEvaluationTarget constant, ReferenceFinderCallback callback) { 430 ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
411 ReferenceFinder referenceFinder = new ReferenceFinder(callback); 431 ReferenceFinder referenceFinder = new ReferenceFinder(callback);
412 if (constant is ParameterElement) { 432 if (constant is ParameterElement) {
413 if (constant.initializer != null) { 433 if (constant.initializer != null) {
414 Expression defaultValue = 434 Expression defaultValue =
415 (constant as ConstVariableElement).constantInitializer; 435 (constant as ConstVariableElement).constantInitializer;
416 if (defaultValue != null) { 436 if (defaultValue != null) {
417 defaultValue.accept(referenceFinder); 437 defaultValue.accept(referenceFinder);
418 } 438 }
419 } 439 }
420 } else if (constant is PotentiallyConstVariableElement) { 440 } else if (constant is PotentiallyConstVariableElement) {
421 Expression initializer = constant.constantInitializer; 441 Expression initializer = constant.constantInitializer;
422 if (initializer != null) { 442 if (initializer != null) {
423 initializer.accept(referenceFinder); 443 initializer.accept(referenceFinder);
424 } 444 }
425 } else if (constant is ConstructorElementImpl) { 445 } else if (constant is ConstructorElementImpl) {
426 constant.isCycleFree = false; 446 if (constant.isConst) {
427 ConstructorElement redirectedConstructor = 447 constant.isCycleFree = false;
428 getConstRedirectedConstructor(constant); 448 ConstructorElement redirectedConstructor =
429 if (redirectedConstructor != null) { 449 getConstRedirectedConstructor(constant);
430 ConstructorElement redirectedConstructorBase = 450 if (redirectedConstructor != null) {
431 ConstantEvaluationEngine._getConstructorBase(redirectedConstructor); 451 ConstructorElement redirectedConstructorBase =
432 callback(redirectedConstructorBase); 452 ConstantEvaluationEngine
433 return; 453 ._getConstructorBase(redirectedConstructor);
434 } else if (constant.isFactory) { 454 callback(redirectedConstructorBase);
435 // Factory constructor, but getConstRedirectedConstructor returned 455 return;
436 // null. This can happen if we're visiting one of the special external 456 } else if (constant.isFactory) {
437 // const factory constructors in the SDK, or if the code contains 457 // Factory constructor, but getConstRedirectedConstructor returned
438 // errors (such as delegating to a non-const constructor, or delegating 458 // null. This can happen if we're visiting one of the special externa l
439 // to a constructor that can't be resolved). In any of these cases, 459 // const factory constructors in the SDK, or if the code contains
440 // we'll evaluate calls to this constructor without having to refer to 460 // errors (such as delegating to a non-const constructor, or delegatin g
441 // any other constants. So we don't need to report any dependencies. 461 // to a constructor that can't be resolved). In any of these cases,
442 return; 462 // we'll evaluate calls to this constructor without having to refer to
443 } 463 // any other constants. So we don't need to report any dependencies.
444 bool superInvocationFound = false; 464 return;
445 List<ConstructorInitializer> initializers = constant.constantInitializers;
446 for (ConstructorInitializer initializer in initializers) {
447 if (initializer is SuperConstructorInvocation) {
448 superInvocationFound = true;
449 } 465 }
450 initializer.accept(referenceFinder); 466 bool superInvocationFound = false;
451 } 467 List<ConstructorInitializer> initializers =
452 if (!superInvocationFound) { 468 constant.constantInitializers;
453 // No explicit superconstructor invocation found, so we need to 469 for (ConstructorInitializer initializer in initializers) {
454 // manually insert a reference to the implicit superconstructor. 470 if (initializer is SuperConstructorInvocation) {
455 InterfaceType superclass = 471 superInvocationFound = true;
456 (constant.returnType as InterfaceType).superclass; 472 }
457 if (superclass != null && !superclass.isObject) { 473 initializer.accept(referenceFinder);
458 ConstructorElement unnamedConstructor = ConstantEvaluationEngine 474 }
459 ._getConstructorBase(superclass.element.unnamedConstructor); 475 if (!superInvocationFound) {
460 if (unnamedConstructor != null && unnamedConstructor.isConst) { 476 // No explicit superconstructor invocation found, so we need to
461 callback(unnamedConstructor); 477 // manually insert a reference to the implicit superconstructor.
478 InterfaceType superclass =
479 (constant.returnType as InterfaceType).superclass;
480 if (superclass != null && !superclass.isObject) {
481 ConstructorElement unnamedConstructor = ConstantEvaluationEngine
482 ._getConstructorBase(superclass.element.unnamedConstructor);
483 if (unnamedConstructor != null) {
484 callback(unnamedConstructor);
485 }
462 } 486 }
463 } 487 }
464 } 488 for (FieldElement field in constant.enclosingElement.fields) {
465 for (FieldElement field in constant.enclosingElement.fields) { 489 // Note: non-static const isn't allowed but we handle it anyway so
466 // Note: non-static const isn't allowed but we handle it anyway so that 490 // that we won't be confused by incorrect code.
467 // we won't be confused by incorrect code. 491 if ((field.isFinal || field.isConst) &&
468 if ((field.isFinal || field.isConst) && 492 !field.isStatic &&
469 !field.isStatic && 493 field.initializer != null) {
470 field.initializer != null) { 494 callback(field);
471 callback(field); 495 }
472 } 496 }
473 } 497 for (ParameterElement parameterElement in constant.parameters) {
474 for (ParameterElement parameterElement in constant.parameters) { 498 callback(parameterElement);
475 callback(parameterElement); 499 }
476 } 500 }
477 } else if (constant is ConstantEvaluationTarget_Annotation) { 501 } else if (constant is ConstantEvaluationTarget_Annotation) {
478 Annotation constNode = constant.annotation; 502 Annotation constNode = constant.annotation;
479 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation; 503 ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
480 // elementAnnotation is null if the annotation couldn't be resolved, in 504 // elementAnnotation is null if the annotation couldn't be resolved, in
481 // which case we skip it. 505 // which case we skip it.
482 if (elementAnnotation != null) { 506 if (elementAnnotation != null) {
483 Element element = elementAnnotation.element; 507 Element element = elementAnnotation.element;
484 if (element is PropertyAccessorElement && 508 if (element is PropertyAccessorElement &&
485 element.variable is VariableElementImpl) { 509 element.variable is VariableElementImpl) {
486 // The annotation is a reference to a compile-time constant variable, 510 // The annotation is a reference to a compile-time constant variable,
487 // so it depends on the variable. 511 // so it depends on the variable.
488 callback(element.variable); 512 callback(element.variable);
489 } else if (element is ConstructorElementImpl && element.isConst) { 513 } else if (element is ConstructorElementImpl) {
490 // The annotation is a constructor invocation, so it depends on the 514 // The annotation is a constructor invocation, so it depends on the
491 // constructor. 515 // constructor.
492 callback(element); 516 callback(element);
493 } else { 517 } else {
494 // This could happen in the event of invalid code. The error will be 518 // This could happen in the event of invalid code. The error will be
495 // reported at constant evaluation time. 519 // reported at constant evaluation time.
496 } 520 }
497 } 521 }
498 if (constNode.arguments != null) { 522 if (constNode.arguments != null) {
499 constNode.arguments.accept(referenceFinder); 523 constNode.arguments.accept(referenceFinder);
(...skipping 4472 matching lines...) Expand 10 before | Expand all | Expand 10 after
4972 } 4996 }
4973 return super.visitInstanceCreationExpression(node); 4997 return super.visitInstanceCreationExpression(node);
4974 } 4998 }
4975 4999
4976 @override 5000 @override
4977 Object visitRedirectingConstructorInvocation( 5001 Object visitRedirectingConstructorInvocation(
4978 RedirectingConstructorInvocation node) { 5002 RedirectingConstructorInvocation node) {
4979 super.visitRedirectingConstructorInvocation(node); 5003 super.visitRedirectingConstructorInvocation(node);
4980 ConstructorElement target = 5004 ConstructorElement target =
4981 ConstantEvaluationEngine._getConstructorBase(node.staticElement); 5005 ConstantEvaluationEngine._getConstructorBase(node.staticElement);
4982 if (target != null && target.isConst) { 5006 if (target != null) {
4983 _callback(target); 5007 _callback(target);
4984 } 5008 }
4985 return null; 5009 return null;
4986 } 5010 }
4987 5011
4988 @override 5012 @override
4989 Object visitSimpleIdentifier(SimpleIdentifier node) { 5013 Object visitSimpleIdentifier(SimpleIdentifier node) {
4990 Element element = node.staticElement; 5014 Element element = node.staticElement;
4991 if (element is PropertyAccessorElement) { 5015 if (element is PropertyAccessorElement) {
4992 element = (element as PropertyAccessorElement).variable; 5016 element = (element as PropertyAccessorElement).variable;
4993 } 5017 }
4994 if (element is VariableElement) { 5018 if (element is VariableElement) {
4995 if (element.isConst) { 5019 _callback(element);
4996 _callback(element);
4997 }
4998 } 5020 }
4999 return null; 5021 return null;
5000 } 5022 }
5001 5023
5002 @override 5024 @override
5003 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { 5025 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
5004 super.visitSuperConstructorInvocation(node); 5026 super.visitSuperConstructorInvocation(node);
5005 ConstructorElement constructor = 5027 ConstructorElement constructor =
5006 ConstantEvaluationEngine._getConstructorBase(node.staticElement); 5028 ConstantEvaluationEngine._getConstructorBase(node.staticElement);
5007 if (constructor != null && constructor.isConst) { 5029 if (constructor != null) {
5008 _callback(constructor); 5030 _callback(constructor);
5009 } 5031 }
5010 return null; 5032 return null;
5011 } 5033 }
5012 } 5034 }
5013 5035
5014 /** 5036 /**
5015 * The state of an object representing a string. 5037 * The state of an object representing a string.
5016 */ 5038 */
5017 class StringState extends InstanceState { 5039 class StringState extends InstanceState {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
5220 return BoolState.from(_element == rightElement); 5242 return BoolState.from(_element == rightElement);
5221 } else if (rightOperand is DynamicState) { 5243 } else if (rightOperand is DynamicState) {
5222 return BoolState.UNKNOWN_VALUE; 5244 return BoolState.UNKNOWN_VALUE;
5223 } 5245 }
5224 return BoolState.FALSE_STATE; 5246 return BoolState.FALSE_STATE;
5225 } 5247 }
5226 5248
5227 @override 5249 @override
5228 String toString() => _element == null ? "-unknown-" : _element.name; 5250 String toString() => _element == null ? "-unknown-" : _element.name;
5229 } 5251 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/all_the_rest_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698