[cfe] Handle exhaustiveness checking in expression evaluation

The expression evaluator called directly into the constant evaluator,
skipping the setting up of the exhaustiveness cache used for
exhaustiveness checking.

Closes #52905

Change-Id: I367ff73d8e23127811f99dfbf451e66eef452443
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/314060
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2023-07-18 10:17:49 +00:00 committed by Commit Queue
parent 06be97c607
commit 33fcaec0f1
3 changed files with 93 additions and 1 deletions

View file

@ -141,7 +141,7 @@ void transformProcedure(
typeEnvironment,
errorReporter,
evaluationMode);
constantsTransformer.visitProcedure(procedure, null);
constantsTransformer.convertProcedure(procedure);
}
enum EvaluationMode {
@ -443,6 +443,14 @@ class ConstantsTransformer extends RemovingTransformer {
_exhaustivenessCache = null;
}
Procedure convertProcedure(Procedure node) {
_exhaustivenessCache =
new CfeExhaustivenessCache(constantEvaluator, node.enclosingLibrary);
Procedure result = visitProcedure(node, null);
_exhaustivenessCache = null;
return result;
}
@override
LibraryPart visitLibraryPart(LibraryPart node, TreeNode? removalSentinel) {
constantEvaluator.withNewEnvironment(() {

View file

@ -0,0 +1,41 @@
# Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
sources: |
class Color {
final String name;
Color(this.name);
}
class Theme {
Color get primary => Color('primary');
Color get white => Color('white');
Color get transparent => Color('transparent');
}
enum _Type {
primary,
background,
outline,
text,
}
class Class {
final _Type _type;
final Theme theme;
final Color? backgroundColor;
Class(this._type, this.theme, this.backgroundColor);
method() {
}
}
definitions: []
position: "#Class"
expression: |
switch (_type) {
_Type.primary => theme.primary,
_Type.background => theme.white,
_Type.outline || _Type.text => theme.transparent,
}

View file

@ -0,0 +1,43 @@
Errors: {
}
method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
return block {
#lib1::Color #t1;
final synthesized #lib1::_Type #0#0 = this.{#lib1::Class::_type}{#lib1::_Type};
#L1:
{
{
if(#C3 =={dart.core::Object::==}{(dart.core::Object) → dart.core::bool} #0#0) {
#t1 = this.{#lib1::Class::theme}{#lib1::Theme}.{#lib1::Theme::primary}{#lib1::Color};
break #L1;
}
}
{
if(#C6 =={dart.core::Object::==}{(dart.core::Object) → dart.core::bool} #0#0) {
#t1 = this.{#lib1::Class::theme}{#lib1::Theme}.{#lib1::Theme::white}{#lib1::Color};
break #L1;
}
}
{
if(#C9 =={dart.core::Object::==}{(dart.core::Object) → dart.core::bool} #0#0 || #C12 =={dart.core::Object::==}{(dart.core::Object) → dart.core::bool} #0#0) {
#t1 = this.{#lib1::Class::theme}{#lib1::Theme}.{#lib1::Theme::transparent}{#lib1::Color};
break #L1;
}
}
throw new dart._internal::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable type.");
}
} =>#t1;
constants {
#C1 = 0
#C2 = "primary"
#C3 = #lib1::_Type {index:#C1, _name:#C2}
#C4 = 1
#C5 = "background"
#C6 = #lib1::_Type {index:#C4, _name:#C5}
#C7 = 2
#C8 = "outline"
#C9 = #lib1::_Type {index:#C7, _name:#C8}
#C10 = 3
#C11 = "text"
#C12 = #lib1::_Type {index:#C10, _name:#C11}
}