[cfe] Support implicit this access to extension methods in extensions

Change-Id: Idad98ca0d0fb27010ef4a522593f283b97ecc873
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117720
Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
Johnni Winther 2019-09-24 07:55:45 +00:00
parent 25166af3ea
commit 71896d5586
14 changed files with 155 additions and 73 deletions

View file

@ -661,9 +661,6 @@ class ThisPropertyAccessGenerator extends Generator {
}
Expression _createRead() {
if (getter == null) {
_helper.warnUnresolvedGet(name, fileOffset);
}
return new PropertyGet(
_forest.createThisExpression(fileOffset), name, getter)
..fileOffset = fileOffset;
@ -675,9 +672,6 @@ class ThisPropertyAccessGenerator extends Generator {
}
Expression _createWrite(int offset, Expression value) {
if (setter == null) {
_helper.warnUnresolvedSet(name, fileOffset);
}
return new PropertySet(
_forest.createThisExpression(fileOffset), name, value, setter)
..fileOffset = fileOffset;
@ -745,9 +739,6 @@ class ThisPropertyAccessGenerator extends Generator {
@override
Expression doInvocation(int offset, Arguments arguments) {
Member interfaceTarget = getter;
if (interfaceTarget == null) {
_helper.warnUnresolvedMethod(name, offset);
}
if (interfaceTarget is Field) {
// TODO(ahe): In strong mode we should probably rewrite this to
// `this.name.call(arguments)`.

View file

@ -0,0 +1,33 @@
// Copyright (c) 2019, 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.
class Class {
int field;
}
extension on Class {
int get property1 => property2;
void set property1(int value) => field = value;
}
extension on Class {
int get property2 => field;
void set property2(int value) => property1 = value;
}
main() {
var c = new Class();
expect(null, c.property1);
expect(null, c.property2);
expect(42, c.property1 = 42);
expect(42, c.property2);
expect(87, c.property2 = 87);
expect(87, c.property1);
}
expect(expected, actual) {
if (expected != actual) {
throw 'Mismatch: expected=$expected, actual=$actual';
}
}

View file

@ -0,0 +1,29 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
field core::int* field;
synthetic constructor •() → self::Class*
;
}
extension _extension#0 on self::Class* {
get property1 = self::_extension#0|get#property1;
set property1 = self::_extension#0|set#property1;
}
extension _extension#1 on self::Class* {
get property2 = self::_extension#1|get#property2;
set property2 = self::_extension#1|set#property2;
}
static method _extension#0|get#property1(final self::Class* #this) → core::int*
;
static method _extension#0|set#property1(final self::Class* #this, core::int* value) → void
;
static method _extension#1|get#property2(final self::Class* #this) → core::int*
;
static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
;
static method main() → dynamic
;
static method expect(dynamic expected, dynamic actual) → dynamic
;

View file

@ -0,0 +1,46 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
field core::int* field = null;
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension _extension#0 on self::Class* {
get property1 = self::_extension#0|get#property1;
set property1 = self::_extension#0|set#property1;
}
extension _extension#1 on self::Class* {
get property2 = self::_extension#1|get#property2;
set property2 = self::_extension#1|set#property2;
}
static method _extension#0|get#property1(final self::Class* #this) → core::int*
return self::_extension#1|get#property2(#this);
static method _extension#0|set#property1(final self::Class* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
return #this.{self::Class::field} = value;
return #t1;
}
static method _extension#1|get#property2(final self::Class* #this) → core::int*
return #this.{self::Class::field};
static method _extension#1|set#property2(final self::Class* #this, core::int* value) → core::int* {
final core::int* #t2 = value;
return self::_extension#0|set#property1(#this, value);
return #t2;
}
static method main() → dynamic {
self::Class* c = new self::Class::•();
self::expect(null, self::_extension#0|get#property1(c));
self::expect(null, self::_extension#1|get#property2(c));
self::expect(42, self::_extension#0|set#property1(c, 42));
self::expect(42, self::_extension#1|get#property2(c));
self::expect(87, self::_extension#1|set#property2(c, 87));
self::expect(87, self::_extension#0|get#property1(c));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}

View file

@ -0,0 +1,46 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
field core::int* field = null;
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension _extension#0 on self::Class* {
get property1 = self::_extension#0|get#property1;
set property1 = self::_extension#0|set#property1;
}
extension _extension#1 on self::Class* {
get property2 = self::_extension#1|get#property2;
set property2 = self::_extension#1|set#property2;
}
static method _extension#0|get#property1(final self::Class* #this) → core::int*
return self::_extension#1|get#property2(#this);
static method _extension#0|set#property1(final self::Class* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
return #this.{self::Class::field} = value;
return #t1;
}
static method _extension#1|get#property2(final self::Class* #this) → core::int*
return #this.{self::Class::field};
static method _extension#1|set#property2(final self::Class* #this, core::int* value) → core::int* {
final core::int* #t2 = value;
return self::_extension#0|set#property1(#this, value);
return #t2;
}
static method main() → dynamic {
self::Class* c = new self::Class::•();
self::expect(null, self::_extension#0|get#property1(c));
self::expect(null, self::_extension#1|get#property2(c));
self::expect(42, self::_extension#0|set#property1(c, 42));
self::expect(42, self::_extension#1|get#property2(c));
self::expect(87, self::_extension#1|set#property2(c, 87));
self::expect(87, self::_extension#0|get#property1(c));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}

View file

@ -2,20 +2,12 @@ library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.

View file

@ -2,20 +2,12 @@ library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/accessors.dart:16:13: Error: Getter not found: 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:16:13: Error: The getter 'onlySetter' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:25:11: Error: Getter not found: 'onlySetter'.
// print(onlySetter);
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/accessors.dart:25:11: Error: The getter 'onlySetter' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/general/accessors.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'onlySetter'.

View file

@ -18,14 +18,6 @@ library;
// for (c.untypedSuperInstanceField in []) {}
// ^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:37:10: Error: Setter not found: 'unresolved'.
// for (unresolved in []) {}
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: Getter not found: 'unresolved'.
// for (unresolved.foo in []) {}
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:20: Error: Unexpected token '.'.
// for (unresolved.foo in []) {}
// ^

View file

@ -18,14 +18,6 @@ library;
// for (c.untypedSuperInstanceField in []) {}
// ^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:37:10: Error: Setter not found: 'unresolved'.
// for (unresolved in []) {}
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: Getter not found: 'unresolved'.
// for (unresolved.foo in []) {}
// ^^^^^^^^^^
//
// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:20: Error: Unexpected token '.'.
// for (unresolved.foo in []) {}
// ^

View file

@ -48,10 +48,6 @@ library;
// C notEvenAConstructor(a) = h;
// ^
//
// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
// C notEvenAConstructor(a) = h;
// ^
//
// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/rasta/issue_000044.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.

View file

@ -48,10 +48,6 @@ library;
// C notEvenAConstructor(a) = h;
// ^
//
// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: Getter not found: 'h'.
// C notEvenAConstructor(a) = h;
// ^
//
// pkg/front_end/testcases/rasta/issue_000044.dart:21:30: Error: The getter 'h' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/rasta/issue_000044.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'h'.

View file

@ -2,14 +2,6 @@ library;
//
// Problems in library:
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:12:13: Error: Getter not found: 'key'.
// print(key);
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:11:10: Error: Setter not found: 'key'.
// for (key in x) {
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Setter not found: 'Fisk'.
// for (Fisk in x) {
// ^^^^
@ -30,10 +22,6 @@ library;
// for (1 in x) {
// ^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:24:13: Error: Getter not found: 'key'.
// print(key);
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
// for (1 in x) {
// ^

View file

@ -2,14 +2,6 @@ library;
//
// Problems in library:
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:12:13: Error: Getter not found: 'key'.
// print(key);
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:11:10: Error: Setter not found: 'key'.
// for (key in x) {
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Setter not found: 'Fisk'.
// for (Fisk in x) {
// ^^^^
@ -30,10 +22,6 @@ library;
// for (1 in x) {
// ^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:24:13: Error: Getter not found: 'key'.
// print(key);
// ^^^
//
// pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
// for (1 in x) {
// ^

View file

@ -20,6 +20,7 @@ extensions/extension_methods: TextSerializationFailure
extensions/implicit_extension_inference: TextSerializationFailure
extensions/implicit_this: TextSerializationFailure
extensions/index: TextSerializationFailure
extensions/internal_resolution: TextSerializationFailure
extensions/instance_access: TextSerializationFailure
extensions/instance_access_of_static: TextSerializationFailure
extensions/instance_members: TextSerializationFailure