[cfe] Handle multiple named record fields in constants

This bypasses the hoisting of record elements in constant record literals.
The created let variables would otherwise interfere with the constant
evaluation.

Closes #49915

Change-Id: Ia70387a0f0c435373dc5fcf5cdd526104db8f394
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/258363
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2022-09-12 10:16:16 +00:00
committed by Commit Bot
parent 51c4e03928
commit 96d52d4e35
9 changed files with 141 additions and 57 deletions
@@ -7317,6 +7317,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
// Index into [positional] of the positional element we find next.
int positionalIndex = positional.length - 1;
// For const literals we don't hoist to avoid using let variables in
// inside constants. Since the elements of the literal must be constant
// themselves, we know that there is no side effects of performing
// constant evaluation out of order.
final bool enableHoisting = !node.isConst;
// Set to `true` if we need to hoist all preceding elements.
bool needsHoisting = false;
@@ -7355,7 +7361,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
if (!namedNeedsSorting && element.name != sortedNames[nameIndex]) {
// Named elements are not sorted, so we need to hoist and sort them.
namedNeedsSorting = true;
needsHoisting = true;
needsHoisting = enableHoisting;
}
nameIndex--;
} else {
@@ -7381,7 +7387,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
if (nameIndex >= 0) {
// We have not seen all named elements yet, so we must hoist the
// remaining named elements and the preceding positional elements.
needsHoisting = true;
needsHoisting = enableHoisting;
}
}
positionalTypes[positionalIndex] = type;
@@ -3,11 +3,19 @@
// BSD-style license that can be found in the LICENSE file.
const dynamic a = (1, 2);
const dynamic b = (a: 1, b: 2);
const dynamic c = (a: a, b: b);
const dynamic d = (c, (1, 2));
const dynamic b1 = (a: 1, b: 2);
const dynamic b2 = (b: 2, a: 1);
const dynamic b3 = (b: 2, 1);
const dynamic c1 = (a: a, b: b1);
const dynamic c2 = (b: b2, a: a);
const dynamic c3 = (b: b3, a);
const dynamic d = (c1, (1, 2));
dynamic e = const (1, 2);
dynamic f = const (a: 1, b: 2);
dynamic g = const (a: a, b: b);
dynamic h = const (c, (1, 2));
dynamic f1 = const (a: 1, b: 2);
dynamic f2 = const (b: 2, a: 1);
dynamic f3 = const (b: 2, 1);
dynamic g1 = const (a: a, b: b1);
dynamic g2 = const (b: b2, a: a);
dynamic g3 = const (b: b3, a);
dynamic h = const (c1, (1, 2));
@@ -3,19 +3,29 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = #C3;
static const field dynamic b = #C4;
static const field dynamic c = #C5;
static const field dynamic d = #C6;
static const field dynamic b1 = #C4;
static const field dynamic b2 = #C4;
static const field dynamic b3 = #C5;
static const field dynamic c1 = #C6;
static const field dynamic c2 = #C6;
static const field dynamic c3 = #C7;
static const field dynamic d = #C8;
static field dynamic e = #C3;
static field dynamic f = #C4;
static field dynamic g = #C5;
static field dynamic h = #C6;
static field dynamic f1 = #C4;
static field dynamic f2 = #C4;
static field dynamic f3 = #C5;
static field dynamic g1 = #C6;
static field dynamic g2 = #C6;
static field dynamic g3 = #C7;
static field dynamic h = #C8;
constants {
#C1 = 1
#C2 = 2
const (#C1, #C2)
const ({a:#C1, b:#C2})
const (#C1, {b:#C2})
const ({a:#C3, b:#C4})
const (#C5, #C3)
const (#C3, {b:#C5})
const (#C6, #C3)
}
@@ -3,19 +3,29 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = #C3;
static const field dynamic b = #C4;
static const field dynamic c = #C5;
static const field dynamic d = #C6;
static const field dynamic b1 = #C4;
static const field dynamic b2 = #C4;
static const field dynamic b3 = #C5;
static const field dynamic c1 = #C6;
static const field dynamic c2 = #C6;
static const field dynamic c3 = #C7;
static const field dynamic d = #C8;
static field dynamic e = #C3;
static field dynamic f = #C4;
static field dynamic g = #C5;
static field dynamic h = #C6;
static field dynamic f1 = #C4;
static field dynamic f2 = #C4;
static field dynamic f3 = #C5;
static field dynamic g1 = #C6;
static field dynamic g2 = #C6;
static field dynamic g3 = #C7;
static field dynamic h = #C8;
constants {
#C1 = 1
#C2 = 2
const (#C1, #C2)
const ({a:#C1, b:#C2})
const (#C1, {b:#C2})
const ({a:#C3, b:#C4})
const (#C5, #C3)
const (#C3, {b:#C5})
const (#C6, #C3)
}
@@ -1,8 +1,16 @@
const dynamic a = (1, 2);
const dynamic b = (a: 1, b: 2);
const dynamic c = (a: a, b: b);
const dynamic d = (c, (1, 2));
const dynamic b1 = (a: 1, b: 2);
const dynamic b2 = (b: 2, a: 1);
const dynamic b3 = (b: 2, 1);
const dynamic c1 = (a: a, b: b1);
const dynamic c2 = (b: b2, a: a);
const dynamic c3 = (b: b3, a);
const dynamic d = (c1, (1, 2));
dynamic e = const (1, 2);
dynamic f = const (a: 1, b: 2);
dynamic g = const (a: a, b: b);
dynamic h = const (c, (1, 2));
dynamic f1 = const (a: 1, b: 2);
dynamic f2 = const (b: 2, a: 1);
dynamic f3 = const (b: 2, 1);
dynamic g1 = const (a: a, b: b1);
dynamic g2 = const (b: b2, a: a);
dynamic g3 = const (b: b3, a);
dynamic h = const (c1, (1, 2));
@@ -3,19 +3,29 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = #C3;
static const field dynamic b = #C4;
static const field dynamic c = #C5;
static const field dynamic d = #C6;
static const field dynamic b1 = #C4;
static const field dynamic b2 = #C4;
static const field dynamic b3 = #C5;
static const field dynamic c1 = #C6;
static const field dynamic c2 = #C6;
static const field dynamic c3 = #C7;
static const field dynamic d = #C8;
static field dynamic e = #C3;
static field dynamic f = #C4;
static field dynamic g = #C5;
static field dynamic h = #C6;
static field dynamic f1 = #C4;
static field dynamic f2 = #C4;
static field dynamic f3 = #C5;
static field dynamic g1 = #C6;
static field dynamic g2 = #C6;
static field dynamic g3 = #C7;
static field dynamic h = #C8;
constants {
#C1 = 1
#C2 = 2
const (#C1, #C2)
const ({a:#C1, b:#C2})
const (#C1, {b:#C2})
const ({a:#C3, b:#C4})
const (#C5, #C3)
const (#C3, {b:#C5})
const (#C6, #C3)
}
@@ -3,19 +3,29 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = #C3;
static const field dynamic b = #C4;
static const field dynamic c = #C5;
static const field dynamic d = #C6;
static const field dynamic b1 = #C4;
static const field dynamic b2 = #C4;
static const field dynamic b3 = #C5;
static const field dynamic c1 = #C6;
static const field dynamic c2 = #C6;
static const field dynamic c3 = #C7;
static const field dynamic d = #C8;
static field dynamic e = #C3;
static field dynamic f = #C4;
static field dynamic g = #C5;
static field dynamic h = #C6;
static field dynamic f1 = #C4;
static field dynamic f2 = #C4;
static field dynamic f3 = #C5;
static field dynamic g1 = #C6;
static field dynamic g2 = #C6;
static field dynamic g3 = #C7;
static field dynamic h = #C8;
constants {
#C1 = 1
#C2 = 2
const (#C1, #C2)
const ({a:#C1, b:#C2})
const (#C1, {b:#C2})
const ({a:#C3, b:#C4})
const (#C5, #C3)
const (#C3, {b:#C5})
const (#C6, #C3)
}
@@ -3,18 +3,30 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = const (1, 2);
static const field dynamic b = const ({a: 1, b: 2});
static const field dynamic c = const ({a: self::a, b: self::b});
static const field dynamic d = const (self::c, const (1, 2));
static const field dynamic b1 = const ({a: 1, b: 2});
static const field dynamic b2 = const ({a: 1, b: 2});
static const field dynamic b3 = const (1, {b: 2});
static const field dynamic c1 = const ({a: self::a, b: self::b1});
static const field dynamic c2 = const ({a: self::a, b: self::b2});
static const field dynamic c3 = const (self::a, {b: self::b3});
static const field dynamic d = const (self::c1, const (1, 2));
static field dynamic e;
static field dynamic f;
static field dynamic g;
static field dynamic f1;
static field dynamic f2;
static field dynamic f3;
static field dynamic g1;
static field dynamic g2;
static field dynamic g3;
static field dynamic h;
Extra constant evaluation status:
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:5:15 -> RecordConstant(const (1, 2))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:6:15 -> RecordConstant(const ({a: 1, b: 2}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:7:15 -> RecordConstant(const ({a: const (1, 2), b: const ({a: 1, b: 2})}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:8:15 -> RecordConstant(const (const ({a: const (1, 2), b: const ({a: 1, b: 2})}), const (1, 2)))
Extra constant evaluation: evaluated: 4, effectively constant: 4
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:7:15 -> RecordConstant(const ({a: 1, b: 2}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:8:15 -> RecordConstant(const (1, {b: 2}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:9:15 -> RecordConstant(const ({a: const (1, 2), b: const ({a: 1, b: 2})}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:10:15 -> RecordConstant(const ({a: const (1, 2), b: const ({a: 1, b: 2})}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:11:15 -> RecordConstant(const (const (1, 2), {b: const (1, {b: 2})}))
Evaluated: RecordLiteral @ org-dartlang-testcase:///const_record_literal.dart:12:15 -> RecordConstant(const (const ({a: const (1, 2), b: const ({a: 1, b: 2})}), const (1, 2)))
Extra constant evaluation: evaluated: 8, effectively constant: 8
@@ -3,19 +3,29 @@ import self as self;
import "dart:core" as core;
static const field dynamic a = #C3;
static const field dynamic b = #C4;
static const field dynamic c = #C5;
static const field dynamic d = #C6;
static const field dynamic b1 = #C4;
static const field dynamic b2 = #C4;
static const field dynamic b3 = #C5;
static const field dynamic c1 = #C6;
static const field dynamic c2 = #C6;
static const field dynamic c3 = #C7;
static const field dynamic d = #C8;
static field dynamic e = #C3;
static field dynamic f = #C4;
static field dynamic g = #C5;
static field dynamic h = #C6;
static field dynamic f1 = #C4;
static field dynamic f2 = #C4;
static field dynamic f3 = #C5;
static field dynamic g1 = #C6;
static field dynamic g2 = #C6;
static field dynamic g3 = #C7;
static field dynamic h = #C8;
constants {
#C1 = 1
#C2 = 2
const (#C1, #C2)
const ({a:#C1, b:#C2})
const (#C1, {b:#C2})
const ({a:#C3, b:#C4})
const (#C5, #C3)
const (#C3, {b:#C5})
const (#C6, #C3)
}