Skip to content

Commit

Permalink
[cfe] Handle inline class representation field in object pattern
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
johnniwinther authored and Commit Queue committed Jul 10, 2023
1 parent 9b9a8cf commit 911b376
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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!,
Expand Down
25 changes: 25 additions & 0 deletions pkg/front_end/testcases/inline_class/issue52667.dart
Original file line number Diff line number Diff line change
@@ -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");
}
}
44 changes: 44 additions & 0 deletions pkg/front_end/testcases/inline_class/issue52667.dart.strong.expect
Original file line number Diff line number Diff line change
@@ -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}");
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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() {}
44 changes: 44 additions & 0 deletions pkg/front_end/testcases/inline_class/issue52667.dart.weak.expect
Original file line number Diff line number Diff line change
@@ -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}");
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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}");
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
;
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions pkg/kernel/lib/src/ast/patterns.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down

0 comments on commit 911b376

Please sign in to comment.