diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart index a6fa9d10e87..87fcdaba04b 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart @@ -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: diff --git a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart index 1c481fffefc..12231e8b11c 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart @@ -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!, diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart b/pkg/front_end/testcases/inline_class/issue52667.dart new file mode 100644 index 00000000000..2dc78a13892 --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart @@ -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"); + } +} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.strong.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.strong.expect new file mode 100644 index 00000000000..6c224bbfe8c --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.strong.expect @@ -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}"); + } + } + } + } +} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.strong.transformed.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.strong.transformed.expect new file mode 100644 index 00000000000..596baf51b46 --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.strong.transformed.expect @@ -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 diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline.expect new file mode 100644 index 00000000000..81795d4bb56 --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline.expect @@ -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() {} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..b62df573ff4 --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.textual_outline_modelled.expect @@ -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() {} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.weak.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.expect new file mode 100644 index 00000000000..6c224bbfe8c --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.expect @@ -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}"); + } + } + } + } +} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.weak.modular.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.modular.expect new file mode 100644 index 00000000000..6c224bbfe8c --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.modular.expect @@ -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}"); + } + } + } + } +} diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.weak.outline.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.outline.expect new file mode 100644 index 00000000000..4cea6bd3e7f --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.outline.expect @@ -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 + ; diff --git a/pkg/front_end/testcases/inline_class/issue52667.dart.weak.transformed.expect b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.transformed.expect new file mode 100644 index 00000000000..596baf51b46 --- /dev/null +++ b/pkg/front_end/testcases/inline_class/issue52667.dart.weak.transformed.expect @@ -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 diff --git a/pkg/kernel/lib/src/ast/patterns.dart b/pkg/kernel/lib/src/ast/patterns.dart index a5ea7c8287a..082d69ab89e 100644 --- a/pkg/kernel/lib/src/ast/patterns.dart +++ b/pkg/kernel/lib/src/ast/patterns.dart @@ -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].