-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix type inference of compound assignments when getter/setter have di…
…fferent types. For compound assignments, we need to look up the "combiner" operation in the type of the getter (not the setter), since the receiver of the combiner operation is the value that was read. This is necessary for soundness. Change-Id: I02e0e93310b6b6b94d4a6253d4cf2fc1d3c69cd5 Reviewed-on: https://dart-review.googlesource.com/16607 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
- Loading branch information
1 parent
39bfbfe
commit cded101
Showing
34 changed files
with
946 additions
and
261 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) 2017, 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. | ||
|
||
/*@testedFeatures=inference*/ | ||
library test; | ||
|
||
T f<T>() => null; | ||
|
||
class A { | ||
C operator +(int value) => null; | ||
C operator *(D value) => null; | ||
} | ||
|
||
class B { | ||
E operator +(int value) => null; | ||
E operator *(F value) => null; | ||
} | ||
|
||
class C extends B {} | ||
|
||
class D {} | ||
|
||
class E {} | ||
|
||
class F {} | ||
|
||
class G { | ||
A operator [](int i) => null; | ||
|
||
void operator []=(int i, B value) {} | ||
} | ||
|
||
void test1(G g) { | ||
g /*@target=G::[]=*/ [0] *= /*@typeArgs=dynamic*/ f(); | ||
var /*@type=C*/ x = g /*@target=G::[]=*/ [0] *= /*@typeArgs=dynamic*/ f(); | ||
} | ||
|
||
void test2(G g) { | ||
++g /*@target=G::[]=*/ [0]; | ||
var /*@type=C*/ x = ++g /*@target=G::[]=*/ [0]; | ||
} | ||
|
||
void test3(G g) { | ||
g /*@target=G::[]=*/ [0]++; | ||
var /*@type=A*/ x = g /*@target=G::[]=*/ [0]++; | ||
} | ||
|
||
main() {} |
65 changes: 65 additions & 0 deletions
65
pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.direct.expect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
library test; | ||
import self as self; | ||
import "dart:core" as core; | ||
|
||
class A extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
operator +(core::int value) → self::C | ||
return null; | ||
operator *(self::D value) → self::C | ||
return null; | ||
} | ||
class B extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
operator +(core::int value) → self::E | ||
return null; | ||
operator *(self::F value) → self::E | ||
return null; | ||
} | ||
class C extends self::B { | ||
default constructor •() → void | ||
: super self::B::•() | ||
; | ||
} | ||
class D extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
} | ||
class E extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
} | ||
class F extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
} | ||
class G extends core::Object { | ||
default constructor •() → void | ||
: super core::Object::•() | ||
; | ||
operator [](core::int i) → self::A | ||
return null; | ||
operator []=(core::int i, self::B value) → void {} | ||
} | ||
static method f<T extends core::Object>() → self::f::T | ||
return null; | ||
static method test1(self::G g) → void { | ||
let final dynamic #t1 = g in let final dynamic #t2 = 0 in #t1.[]=(#t2, #t1.[](#t2).*(self::f<dynamic>())); | ||
dynamic x = let final dynamic #t3 = g in let final dynamic #t4 = 0 in let final dynamic #t5 = #t3.[](#t4).*(self::f<dynamic>()) in let final dynamic #t6 = #t3.[]=(#t4, #t5) in #t5; | ||
} | ||
static method test2(self::G g) → void { | ||
let final dynamic #t7 = g in let final dynamic #t8 = 0 in let final dynamic #t9 = #t7.[](#t8).+(1) in let final dynamic #t10 = #t7.[]=(#t8, #t9) in #t9; | ||
dynamic x = let final dynamic #t11 = g in let final dynamic #t12 = 0 in let final dynamic #t13 = #t11.[](#t12).+(1) in let final dynamic #t14 = #t11.[]=(#t12, #t13) in #t13; | ||
} | ||
static method test3(self::G g) → void { | ||
let final dynamic #t15 = g in let final dynamic #t16 = 0 in #t15.[]=(#t16, #t15.[](#t16).+(1)); | ||
dynamic x = let final dynamic #t17 = g in let final dynamic #t18 = 0 in let final dynamic #t19 = #t17.[](#t18) in let final dynamic #t20 = #t17.[]=(#t18, #t19.+(1)) in #t19; | ||
} | ||
static method main() → dynamic {} |
54 changes: 54 additions & 0 deletions
54
pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.outline.expect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
library test; | ||
import self as self; | ||
import "dart:core" as core; | ||
|
||
class A extends core::Object { | ||
default constructor •() → void | ||
; | ||
operator +(core::int value) → self::C | ||
; | ||
operator *(self::D value) → self::C | ||
; | ||
} | ||
class B extends core::Object { | ||
default constructor •() → void | ||
; | ||
operator +(core::int value) → self::E | ||
; | ||
operator *(self::F value) → self::E | ||
; | ||
} | ||
class C extends self::B { | ||
default constructor •() → void | ||
; | ||
} | ||
class D extends core::Object { | ||
default constructor •() → void | ||
; | ||
} | ||
class E extends core::Object { | ||
default constructor •() → void | ||
; | ||
} | ||
class F extends core::Object { | ||
default constructor •() → void | ||
; | ||
} | ||
class G extends core::Object { | ||
default constructor •() → void | ||
; | ||
operator [](core::int i) → self::A | ||
; | ||
operator []=(core::int i, self::B value) → void | ||
; | ||
} | ||
static method f<T extends core::Object>() → self::f::T | ||
; | ||
static method test1(self::G g) → void | ||
; | ||
static method test2(self::G g) → void | ||
; | ||
static method test3(self::G g) → void | ||
; | ||
static method main() → dynamic | ||
; |
Oops, something went wrong.