mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:09:48 +00:00
[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:
parent
9b9a8cf042
commit
911b376f7e
|
@ -10429,6 +10429,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||||
case ObjectAccessTargetKind.nullableCallFunction:
|
case ObjectAccessTargetKind.nullableCallFunction:
|
||||||
case ObjectAccessTargetKind.missing:
|
case ObjectAccessTargetKind.missing:
|
||||||
case ObjectAccessTargetKind.ambiguous:
|
case ObjectAccessTargetKind.ambiguous:
|
||||||
|
case ObjectAccessTargetKind.nullableInlineClassRepresentation:
|
||||||
field.pattern = new InvalidPattern(
|
field.pattern = new InvalidPattern(
|
||||||
createMissingPropertyGet(
|
createMissingPropertyGet(
|
||||||
field.fileOffset, node.requiredType, field.fieldName),
|
field.fileOffset, node.requiredType, field.fieldName),
|
||||||
|
@ -10443,9 +10444,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||||
case ObjectAccessTargetKind.callFunction:
|
case ObjectAccessTargetKind.callFunction:
|
||||||
field.accessKind = ObjectAccessKind.FunctionTearOff;
|
field.accessKind = ObjectAccessKind.FunctionTearOff;
|
||||||
break;
|
break;
|
||||||
case ObjectAccessTargetKind.superMember:
|
|
||||||
case ObjectAccessTargetKind.inlineClassRepresentation:
|
case ObjectAccessTargetKind.inlineClassRepresentation:
|
||||||
case ObjectAccessTargetKind.nullableInlineClassRepresentation:
|
field.accessKind = ObjectAccessKind.Direct;
|
||||||
|
field.resultType = fieldTarget.getGetterType(this);
|
||||||
|
case ObjectAccessTargetKind.superMember:
|
||||||
problems.unsupported(
|
problems.unsupported(
|
||||||
'Object field target $fieldTarget', node.fileOffset, helper.uri);
|
'Object field target $fieldTarget', node.fileOffset, helper.uri);
|
||||||
case ObjectAccessTargetKind.extensionMember:
|
case ObjectAccessTargetKind.extensionMember:
|
||||||
|
|
|
@ -423,6 +423,10 @@ class MatchingExpressionVisitor
|
||||||
typedMatchedExpression, field.target!, field.resultType!,
|
typedMatchedExpression, field.target!, field.resultType!,
|
||||||
isObjectAccess: false, fileOffset: field.fileOffset);
|
isObjectAccess: false, fileOffset: field.fileOffset);
|
||||||
break;
|
break;
|
||||||
|
case ObjectAccessKind.Direct:
|
||||||
|
expression = new DelayedAsExpression(
|
||||||
|
typedMatchedExpression, field.resultType!,
|
||||||
|
isUnchecked: true, fileOffset: field.fileOffset);
|
||||||
case ObjectAccessKind.Static:
|
case ObjectAccessKind.Static:
|
||||||
expression = new DelayedExtensionInvocation(field.target as Procedure,
|
expression = new DelayedExtensionInvocation(field.target as Procedure,
|
||||||
[typedMatchedExpression], field.typeArguments!, field.resultType!,
|
[typedMatchedExpression], field.typeArguments!, field.resultType!,
|
||||||
|
|
25
pkg/front_end/testcases/inline_class/issue52667.dart
Normal file
25
pkg/front_end/testcases/inline_class/issue52667.dart
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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() {}
|
|
@ -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() {}
|
|
@ -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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
;
|
|
@ -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
|
|
@ -1604,6 +1604,9 @@ enum ObjectAccessKind {
|
||||||
|
|
||||||
/// Erroneous property access.
|
/// Erroneous property access.
|
||||||
Error,
|
Error,
|
||||||
|
|
||||||
|
/// Access of an inline class representation field.
|
||||||
|
Direct,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [Pattern] with an optional guard [Expression].
|
/// A [Pattern] with an optional guard [Expression].
|
||||||
|
|
Loading…
Reference in a new issue