mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:35:46 +00:00
[cfe] Implement least upper bound for inline types
Closes #51556 Change-Id: I44f2ae947b5316d21d23b39b88f1515702525955 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294983 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
92239e6b27
commit
fe01a2068d
|
@ -41,6 +41,7 @@ approximation
|
|||
arbitrarily
|
||||
area
|
||||
arglebargle
|
||||
arr
|
||||
asdf
|
||||
asserter
|
||||
assure
|
||||
|
|
44
pkg/front_end/testcases/inline_class/issue51556.dart
Normal file
44
pkg/front_end/testcases/inline_class/issue51556.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
// 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.
|
||||
|
||||
inline class JSAny {
|
||||
final Object value;
|
||||
JSAny(this.value);
|
||||
}
|
||||
|
||||
inline class JSObject implements JSAny {
|
||||
final Object value;
|
||||
JSObject(this.value);
|
||||
}
|
||||
|
||||
inline class JSArray implements JSObject {
|
||||
final List<JSAny?> value;
|
||||
JSArray(this.value);
|
||||
}
|
||||
|
||||
inline class JSExportedDartObject implements JSObject {
|
||||
final Object value;
|
||||
JSExportedDartObject(this.value);
|
||||
}
|
||||
|
||||
inline class JSNumber implements JSAny {
|
||||
final double value;
|
||||
JSNumber(this.value);
|
||||
}
|
||||
|
||||
extension ObjectToJSExportedDartObject on Object {
|
||||
JSExportedDartObject get toJS => JSExportedDartObject(this);
|
||||
}
|
||||
|
||||
extension ListToJSArray on List<JSAny?> {
|
||||
JSArray get toJS => JSArray(this);
|
||||
}
|
||||
|
||||
extension DoubleToJSNumber on double {
|
||||
JSNumber get toJS => JSNumber(this);
|
||||
}
|
||||
|
||||
void main() {
|
||||
JSArray arr = [1.0.toJS, 'foo'.toJS].toJS;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny {
|
||||
final self::JSAny #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject {
|
||||
final self::JSObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray {
|
||||
final self::JSArray #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject {
|
||||
final self::JSExportedDartObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber {
|
||||
final self::JSNumber #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(#this);
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
return self::JSArray|(#this);
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
return self::JSNumber|(#this);
|
||||
static method main() → void {
|
||||
self::JSArray arr = self::ListToJSArray|get#toJS(<self::JSAny>[self::DoubleToJSNumber|get#toJS(1.0), self::ObjectToJSExportedDartObject|get#toJS("foo")]);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny {
|
||||
final self::JSAny #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject {
|
||||
final self::JSObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray {
|
||||
final self::JSArray #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject {
|
||||
final self::JSExportedDartObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber {
|
||||
final self::JSNumber #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(#this);
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
return self::JSArray|(#this);
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
return self::JSNumber|(#this);
|
||||
static method main() → void {
|
||||
self::JSArray arr = self::ListToJSArray|get#toJS(core::_GrowableList::_literal2<self::JSAny>(self::DoubleToJSNumber|get#toJS(1.0), self::ObjectToJSExportedDartObject|get#toJS("foo")));
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
inline class JSAny {
|
||||
final Object value;
|
||||
JSAny(this.value);
|
||||
}
|
||||
|
||||
inline class JSObject implements JSAny {
|
||||
final Object value;
|
||||
JSObject(this.value);
|
||||
}
|
||||
|
||||
inline class JSArray implements JSObject {
|
||||
final List<JSAny?> value;
|
||||
JSArray(this.value);
|
||||
}
|
||||
|
||||
inline class JSExportedDartObject implements JSObject {
|
||||
final Object value;
|
||||
JSExportedDartObject(this.value);
|
||||
}
|
||||
|
||||
inline class JSNumber implements JSAny {
|
||||
final double value;
|
||||
JSNumber(this.value);
|
||||
}
|
||||
|
||||
extension ObjectToJSExportedDartObject on Object {
|
||||
JSExportedDartObject get toJS => JSExportedDartObject(this);
|
||||
}
|
||||
|
||||
extension ListToJSArray on List<JSAny?> {
|
||||
JSArray get toJS => JSArray(this);
|
||||
}
|
||||
|
||||
extension DoubleToJSNumber on double {
|
||||
JSNumber get toJS => JSNumber(this);
|
||||
}
|
||||
|
||||
void main() {}
|
|
@ -0,0 +1,38 @@
|
|||
extension DoubleToJSNumber on double {
|
||||
JSNumber get toJS => JSNumber(this);
|
||||
}
|
||||
|
||||
extension ListToJSArray on List<JSAny?> {
|
||||
JSArray get toJS => JSArray(this);
|
||||
}
|
||||
|
||||
extension ObjectToJSExportedDartObject on Object {
|
||||
JSExportedDartObject get toJS => JSExportedDartObject(this);
|
||||
}
|
||||
|
||||
inline class JSAny {
|
||||
JSAny(this.value);
|
||||
final Object value;
|
||||
}
|
||||
|
||||
inline class JSArray implements JSObject {
|
||||
JSArray(this.value);
|
||||
final List<JSAny?> value;
|
||||
}
|
||||
|
||||
inline class JSExportedDartObject implements JSObject {
|
||||
JSExportedDartObject(this.value);
|
||||
final Object value;
|
||||
}
|
||||
|
||||
inline class JSNumber implements JSAny {
|
||||
JSNumber(this.value);
|
||||
final double value;
|
||||
}
|
||||
|
||||
inline class JSObject implements JSAny {
|
||||
JSObject(this.value);
|
||||
final Object value;
|
||||
}
|
||||
|
||||
void main() {}
|
|
@ -0,0 +1,72 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny {
|
||||
final self::JSAny #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject {
|
||||
final self::JSObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray {
|
||||
final self::JSArray #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject {
|
||||
final self::JSExportedDartObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber {
|
||||
final self::JSNumber #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(#this);
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
return self::JSArray|(#this);
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
return self::JSNumber|(#this);
|
||||
static method main() → void {
|
||||
self::JSArray arr = self::ListToJSArray|get#toJS(<self::JSAny>[self::DoubleToJSNumber|get#toJS(1.0), self::ObjectToJSExportedDartObject|get#toJS("foo")]);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny {
|
||||
final self::JSAny #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject {
|
||||
final self::JSObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray {
|
||||
final self::JSArray #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject {
|
||||
final self::JSExportedDartObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber {
|
||||
final self::JSNumber #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(#this);
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
return self::JSArray|(#this);
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
return self::JSNumber|(#this);
|
||||
static method main() → void {
|
||||
self::JSArray arr = self::ListToJSArray|get#toJS(<self::JSAny>[self::DoubleToJSNumber|get#toJS(1.0), self::ObjectToJSExportedDartObject|get#toJS("foo")]);
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny
|
||||
;
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject
|
||||
;
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray
|
||||
;
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject
|
||||
;
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber
|
||||
;
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
;
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
;
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
;
|
||||
static method main() → void
|
||||
;
|
|
@ -0,0 +1,72 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension ObjectToJSExportedDartObject on core::Object {
|
||||
get toJS = self::ObjectToJSExportedDartObject|get#toJS;
|
||||
}
|
||||
extension ListToJSArray on core::List<self::JSAny?> {
|
||||
get toJS = self::ListToJSArray|get#toJS;
|
||||
}
|
||||
extension DoubleToJSNumber on core::double {
|
||||
get toJS = self::DoubleToJSNumber|get#toJS;
|
||||
}
|
||||
inline class JSAny /* declaredRepresentationType = core::Object */ {
|
||||
constructor • = self::JSAny|;
|
||||
tearoff • = self::JSAny|get#;
|
||||
}
|
||||
inline class JSObject /* declaredRepresentationType = core::Object */ implements self::JSAny {
|
||||
constructor • = self::JSObject|;
|
||||
tearoff • = self::JSObject|get#;
|
||||
}
|
||||
inline class JSArray /* declaredRepresentationType = core::List<self::JSAny?> */ implements self::JSObject {
|
||||
constructor • = self::JSArray|;
|
||||
tearoff • = self::JSArray|get#;
|
||||
}
|
||||
inline class JSExportedDartObject /* declaredRepresentationType = core::Object */ implements self::JSObject {
|
||||
constructor • = self::JSExportedDartObject|;
|
||||
tearoff • = self::JSExportedDartObject|get#;
|
||||
}
|
||||
inline class JSNumber /* declaredRepresentationType = core::double */ implements self::JSAny {
|
||||
constructor • = self::JSNumber|;
|
||||
tearoff • = self::JSNumber|get#;
|
||||
}
|
||||
static method JSAny|(core::Object value) → self::JSAny {
|
||||
final self::JSAny #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSAny|get#(core::Object value) → self::JSAny
|
||||
return self::JSAny|(value);
|
||||
static method JSObject|(core::Object value) → self::JSObject {
|
||||
final self::JSObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSObject|get#(core::Object value) → self::JSObject
|
||||
return self::JSObject|(value);
|
||||
static method JSArray|(core::List<self::JSAny?> value) → self::JSArray {
|
||||
final self::JSArray #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSArray|get#(core::List<self::JSAny?> value) → self::JSArray
|
||||
return self::JSArray|(value);
|
||||
static method JSExportedDartObject|(core::Object value) → self::JSExportedDartObject {
|
||||
final self::JSExportedDartObject #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSExportedDartObject|get#(core::Object value) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(value);
|
||||
static method JSNumber|(core::double value) → self::JSNumber {
|
||||
final self::JSNumber #this = value;
|
||||
return #this;
|
||||
}
|
||||
static method JSNumber|get#(core::double value) → self::JSNumber
|
||||
return self::JSNumber|(value);
|
||||
static method ObjectToJSExportedDartObject|get#toJS(lowered final core::Object #this) → self::JSExportedDartObject
|
||||
return self::JSExportedDartObject|(#this);
|
||||
static method ListToJSArray|get#toJS(lowered final core::List<self::JSAny?> #this) → self::JSArray
|
||||
return self::JSArray|(#this);
|
||||
static method DoubleToJSNumber|get#toJS(lowered final core::double #this) → self::JSNumber
|
||||
return self::JSNumber|(#this);
|
||||
static method main() → void {
|
||||
self::JSArray arr = self::ListToJSArray|get#toJS(core::_GrowableList::_literal2<self::JSAny>(self::DoubleToJSNumber|get#toJS(1.0), self::ObjectToJSExportedDartObject|get#toJS("foo")));
|
||||
}
|
|
@ -865,22 +865,22 @@ mixin StandardBounds {
|
|||
}
|
||||
|
||||
// UP(T1, T2) = T2 if T1 <: T2
|
||||
// Note that both types must be class types at this point.
|
||||
assert(type1 is InterfaceType,
|
||||
// Note that both types must be interface or inline types at this point.
|
||||
assert(type1 is InterfaceType || type1 is InlineType,
|
||||
"Expected type1 to be an interface type, got '${type1.runtimeType}'.");
|
||||
assert(type2 is InterfaceType,
|
||||
assert(type2 is InterfaceType || type2 is InlineType,
|
||||
"Expected type2 to be an interface type, got '${type2.runtimeType}'.");
|
||||
|
||||
// We use the non-nullable variants of the two interfaces types to determine
|
||||
// T1 <: T2 without using the nullability of the outermost type. The result
|
||||
// uses [uniteNullabilities] to compute the resulting type if the subtype
|
||||
// relation is established.
|
||||
InterfaceType typeWithoutNullabilityMarker1 =
|
||||
DartType typeWithoutNullabilityMarker1 =
|
||||
computeTypeWithoutNullabilityMarker(type1,
|
||||
isNonNullableByDefault: isNonNullableByDefault) as InterfaceType;
|
||||
InterfaceType typeWithoutNullabilityMarker2 =
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
DartType typeWithoutNullabilityMarker2 =
|
||||
computeTypeWithoutNullabilityMarker(type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault) as InterfaceType;
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
|
||||
if (isSubtypeOf(typeWithoutNullabilityMarker1,
|
||||
typeWithoutNullabilityMarker2, SubtypeCheckMode.withNullabilities)) {
|
||||
|
@ -889,7 +889,7 @@ mixin StandardBounds {
|
|||
}
|
||||
|
||||
// UP(T1, T2) = T1 if T2 <: T1
|
||||
// Note that both types must be class types at this point.
|
||||
// Note that both types must be interface or inline types at this point.
|
||||
if (isSubtypeOf(typeWithoutNullabilityMarker2,
|
||||
typeWithoutNullabilityMarker1, SubtypeCheckMode.withNullabilities)) {
|
||||
return type1.withDeclaredNullability(uniteNullabilities(
|
||||
|
@ -897,33 +897,59 @@ mixin StandardBounds {
|
|||
}
|
||||
|
||||
// UP(C<T0, ..., Tn>, C<S0, ..., Sn>) = C<R0,..., Rn> where Ri is UP(Ti, Si)
|
||||
Class? cls;
|
||||
InlineClass? inlineClass;
|
||||
List<TypeParameter>? typeParameters;
|
||||
List<DartType>? leftArguments;
|
||||
List<DartType>? rightArguments;
|
||||
if (type1 is InterfaceType && type2 is InterfaceType) {
|
||||
Class klass = type1.classNode;
|
||||
if (type2.classNode == klass) {
|
||||
int n = klass.typeParameters.length;
|
||||
List<DartType> leftArguments = type1.typeArguments;
|
||||
List<DartType> rightArguments = type2.typeArguments;
|
||||
List<DartType> typeArguments = new List<DartType>.of(leftArguments);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int variance = klass.typeParameters[i].variance;
|
||||
if (variance == Variance.contravariant) {
|
||||
typeArguments[i] = _getNullabilityAwareStandardLowerBound(
|
||||
leftArguments[i], rightArguments[i],
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else if (variance == Variance.invariant) {
|
||||
if (!areMutualSubtypes(leftArguments[i], rightArguments[i],
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
return hierarchy.getLegacyLeastUpperBound(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
} else {
|
||||
typeArguments[i] = _getNullabilityAwareStandardUpperBound(
|
||||
leftArguments[i], rightArguments[i],
|
||||
if (type1.classNode == type2.classNode) {
|
||||
cls = type1.classNode;
|
||||
typeParameters = cls.typeParameters;
|
||||
leftArguments = type1.typeArguments;
|
||||
rightArguments = type2.typeArguments;
|
||||
}
|
||||
}
|
||||
if (type1 is InlineType && type2 is InlineType) {
|
||||
if (type1.inlineClass == type2.inlineClass) {
|
||||
inlineClass = type1.inlineClass;
|
||||
leftArguments = type1.typeArguments;
|
||||
rightArguments = type2.typeArguments;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeParameters != null &&
|
||||
leftArguments != null &&
|
||||
rightArguments != null) {
|
||||
int n = typeParameters.length;
|
||||
List<DartType> typeArguments = new List<DartType>.of(leftArguments);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int variance = typeParameters[i].variance;
|
||||
if (variance == Variance.contravariant) {
|
||||
typeArguments[i] = _getNullabilityAwareStandardLowerBound(
|
||||
leftArguments[i], rightArguments[i],
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else if (variance == Variance.invariant) {
|
||||
if (!areMutualSubtypes(leftArguments[i], rightArguments[i],
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
return _getLegacyLeastUpperBound(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
} else {
|
||||
typeArguments[i] = _getNullabilityAwareStandardUpperBound(
|
||||
leftArguments[i], rightArguments[i],
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
}
|
||||
if (cls != null) {
|
||||
return new InterfaceType(
|
||||
klass,
|
||||
cls,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
} else {
|
||||
return new InlineType(
|
||||
inlineClass!,
|
||||
uniteNullabilities(
|
||||
type1.declaredNullability, type2.declaredNullability),
|
||||
typeArguments);
|
||||
|
@ -932,11 +958,79 @@ mixin StandardBounds {
|
|||
|
||||
// UP(C0<T0, ..., Tn>, C1<S0, ..., Sk>)
|
||||
// = least upper bound of two interfaces as in Dart 1.
|
||||
return hierarchy.getLegacyLeastUpperBound(
|
||||
type1 as InterfaceType, type2 as InterfaceType,
|
||||
return _getLegacyLeastUpperBound(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
|
||||
DartType _getLegacyLeastUpperBound(DartType type1, DartType type2,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
if (type1 is InterfaceType && type2 is InterfaceType) {
|
||||
return hierarchy.getLegacyLeastUpperBound(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else if (type1 is InlineType && type2 is InlineType) {
|
||||
// This mimics the legacy least upper bound implementation for regular
|
||||
// classes, where the least upper bound is found as the single common
|
||||
// supertype with the highest class hierarchy depth.
|
||||
|
||||
// TODO(johnniwinther): Move this computation to [ClassHierarchyBase] and
|
||||
// cache it there.
|
||||
Map<InlineClass, int> inlineClassDepth = {};
|
||||
|
||||
int computeInlineClassDepth(InlineClass inlineClass) {
|
||||
int? depth = inlineClassDepth[inlineClass];
|
||||
if (depth == null) {
|
||||
int maxDepth = 0;
|
||||
for (InlineType implemented in inlineClass.implements) {
|
||||
int supertypeDepth =
|
||||
computeInlineClassDepth(implemented.inlineClass);
|
||||
if (supertypeDepth >= maxDepth) {
|
||||
maxDepth = supertypeDepth + 1;
|
||||
}
|
||||
}
|
||||
depth = inlineClassDepth[inlineClass] = maxDepth;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
void computeSuperTypes(InlineType type, List<InlineType> supertypes) {
|
||||
computeInlineClassDepth(type.inlineClass);
|
||||
supertypes.add(type);
|
||||
for (InlineType implemented in type.inlineClass.implements) {
|
||||
InlineType supertype = hierarchy.getInlineTypeAsInstanceOf(
|
||||
type, implemented.inlineClass,
|
||||
isNonNullableByDefault: isNonNullableByDefault)!;
|
||||
computeSuperTypes(supertype, supertypes);
|
||||
}
|
||||
}
|
||||
|
||||
List<InlineType> supertypes1 = [];
|
||||
computeSuperTypes(type1, supertypes1);
|
||||
List<InlineType> supertypes2 = [];
|
||||
computeSuperTypes(type2, supertypes2);
|
||||
|
||||
Set<InlineType> set = supertypes1.toSet()..retainAll(supertypes2);
|
||||
Map<int, List<InlineType>> commonSupertypesByDepth = {};
|
||||
for (InlineType type in set) {
|
||||
(commonSupertypesByDepth[inlineClassDepth[type.inlineClass]!] ??= [])
|
||||
.add(type);
|
||||
}
|
||||
int maxDepth = -1;
|
||||
InlineType? candidate;
|
||||
for (MapEntry<int, List<InlineType>> entry
|
||||
in commonSupertypesByDepth.entries) {
|
||||
if (entry.key > maxDepth && entry.value.length == 1) {
|
||||
maxDepth = entry.key;
|
||||
candidate = entry.value.single;
|
||||
}
|
||||
}
|
||||
if (candidate != null) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return coreTypes.objectRawType(
|
||||
uniteNullabilities(type1.nullability, type2.nullability));
|
||||
}
|
||||
|
||||
/// Computes the nullability-aware lower bound of two function types.
|
||||
///
|
||||
/// The algorithm is defined as follows:
|
||||
|
|
Loading…
Reference in a new issue