[cfe] Handle inline class representation field in object pattern

Closes #52667

Change-Id: I9c6d51597ff27ae3a7cdeed29d75755c18a2d530
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311742
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Johnni Winther 2023-07-10 11:02:50 +00:00 committed by Commit Queue
parent 9b9a8cf042
commit 911b376f7e
12 changed files with 318 additions and 2 deletions

View file

@ -10429,6 +10429,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.missing:
case ObjectAccessTargetKind.ambiguous:
case ObjectAccessTargetKind.nullableInlineClassRepresentation:
field.pattern = new InvalidPattern(
createMissingPropertyGet(
field.fileOffset, node.requiredType, field.fieldName),
@ -10443,9 +10444,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
case ObjectAccessTargetKind.callFunction:
field.accessKind = ObjectAccessKind.FunctionTearOff;
break;
case ObjectAccessTargetKind.superMember:
case ObjectAccessTargetKind.inlineClassRepresentation:
case ObjectAccessTargetKind.nullableInlineClassRepresentation:
field.accessKind = ObjectAccessKind.Direct;
field.resultType = fieldTarget.getGetterType(this);
case ObjectAccessTargetKind.superMember:
problems.unsupported(
'Object field target $fieldTarget', node.fileOffset, helper.uri);
case ObjectAccessTargetKind.extensionMember:

View file

@ -423,6 +423,10 @@ class MatchingExpressionVisitor
typedMatchedExpression, field.target!, field.resultType!,
isObjectAccess: false, fileOffset: field.fileOffset);
break;
case ObjectAccessKind.Direct:
expression = new DelayedAsExpression(
typedMatchedExpression, field.resultType!,
isUnchecked: true, fileOffset: field.fileOffset);
case ObjectAccessKind.Static:
expression = new DelayedExtensionInvocation(field.target as Procedure,
[typedMatchedExpression], field.typeArguments!, field.resultType!,

View file

@ -0,0 +1,25 @@
// 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.
abstract class Foo {}
inline class FooBar implements Foo {
final int i;
const FooBar(this.i);
}
inline class FooBaz implements Foo {
final int i;
const FooBaz(this.i);
}
void main() {
final a = FooBar(0);
switch (a) {
case FooBar(i: final a):
print("FooBar $a");
}
}

View file

@ -0,0 +1,44 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
: super core::Object::•()
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar {
lowered final self::FooBar #this = i;
return #this;
}
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz {
lowered final self::FooBaz #this = i;
return #this;
}
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void {
final self::FooBar a = self::FooBar|(0);
#L1:
{
final synthesized self::FooBar #0#0 = a;
{
final hoisted core::int a;
if(let final dynamic #t1 = a = #0#0 as{Unchecked} core::int in true) {
{
core::print("FooBar ${a}");
}
}
}
}
}

View file

@ -0,0 +1,49 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
: super core::Object::•()
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar {
lowered final self::FooBar #this = i;
return #this;
}
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz {
lowered final self::FooBaz #this = i;
return #this;
}
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void {
final self::FooBar a = self::FooBar|(0);
#L1:
{
final synthesized self::FooBar #0#0 = a;
{
final hoisted core::int a;
if(let final core::int #t1 = a = #0#0 as{Unchecked} core::int in true) {
{
core::print("FooBar ${a}");
}
}
}
}
}
Extra constant evaluation status:
Evaluated: FactoryConstructorInvocation @ org-dartlang-testcase:///issue52667.dart:20:13 -> IntConstant(0)
Extra constant evaluation: evaluated: 17, effectively constant: 1

View file

@ -0,0 +1,13 @@
abstract class Foo {}
inline class FooBar implements Foo {
final int i;
const FooBar(this.i);
}
inline class FooBaz implements Foo {
final int i;
const FooBaz(this.i);
}
void main() {}

View file

@ -0,0 +1,13 @@
abstract class Foo {}
inline class FooBar implements Foo {
const FooBar(this.i);
final int i;
}
inline class FooBaz implements Foo {
const FooBaz(this.i);
final int i;
}
void main() {}

View file

@ -0,0 +1,44 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
: super core::Object::•()
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar {
lowered final self::FooBar #this = i;
return #this;
}
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz {
lowered final self::FooBaz #this = i;
return #this;
}
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void {
final self::FooBar a = self::FooBar|(0);
#L1:
{
final synthesized self::FooBar #0#0 = a;
{
final hoisted core::int a;
if(let final dynamic #t1 = a = #0#0 as{Unchecked} core::int in true) {
{
core::print("FooBar ${a}");
}
}
}
}
}

View file

@ -0,0 +1,44 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
: super core::Object::•()
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar {
lowered final self::FooBar #this = i;
return #this;
}
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz {
lowered final self::FooBaz #this = i;
return #this;
}
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void {
final self::FooBar a = self::FooBar|(0);
#L1:
{
final synthesized self::FooBar #0#0 = a;
{
final hoisted core::int a;
if(let final dynamic #t1 = a = #0#0 as{Unchecked} core::int in true) {
{
core::print("FooBar ${a}");
}
}
}
}
}

View file

@ -0,0 +1,26 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar
;
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz
;
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void
;

View file

@ -0,0 +1,49 @@
library;
import self as self;
import "dart:core" as core;
abstract class Foo extends core::Object {
synthetic constructor •() → self::Foo
: super core::Object::•()
;
}
inline class FooBar /* declaredRepresentationType = core::int */ {
constructor • = self::FooBar|;
tearoff • = self::FooBar|_#new#tearOff;
}
inline class FooBaz /* declaredRepresentationType = core::int */ {
constructor • = self::FooBaz|;
tearoff • = self::FooBaz|_#new#tearOff;
}
static inline-class-member method FooBar|(core::int i) → self::FooBar {
lowered final self::FooBar #this = i;
return #this;
}
static inline-class-member method FooBar|_#new#tearOff(core::int i) → self::FooBar
return self::FooBar|(i);
static inline-class-member method FooBaz|(core::int i) → self::FooBaz {
lowered final self::FooBaz #this = i;
return #this;
}
static inline-class-member method FooBaz|_#new#tearOff(core::int i) → self::FooBaz
return self::FooBaz|(i);
static method main() → void {
final self::FooBar a = self::FooBar|(0);
#L1:
{
final synthesized self::FooBar #0#0 = a;
{
final hoisted core::int a;
if(let final core::int #t1 = a = #0#0 as{Unchecked} core::int in true) {
{
core::print("FooBar ${a}");
}
}
}
}
}
Extra constant evaluation status:
Evaluated: FactoryConstructorInvocation @ org-dartlang-testcase:///issue52667.dart:20:13 -> IntConstant(0)
Extra constant evaluation: evaluated: 17, effectively constant: 1

View file

@ -1604,6 +1604,9 @@ enum ObjectAccessKind {
/// Erroneous property access.
Error,
/// Access of an inline class representation field.
Direct,
}
/// A [Pattern] with an optional guard [Expression].