Skip to content

Commit

Permalink
dart-lang#1400. More static analysis of the inline class tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrekhov committed May 30, 2023
1 parent da1fae6 commit 5ceb054
Show file tree
Hide file tree
Showing 14 changed files with 671 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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.

// 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.

/// @assertion Assume that T1, .. Ts are types, and V resolves to an inline
/// class declaration of the following form:
///
/// inline class V<X1 extends B1, .. Xs extends Bs> ... {
/// final T id;
/// V(this.id);
///
/// ... // Other members.
/// }
/// ...
/// When s is zero, V<T1, .. Ts> simply stands for V, a non-generic inline type.
/// When s is greater than zero, a raw occurrence V is treated like a raw type:
/// Instantiation to bound is used to obtain the omitted type arguments
///
/// @description Checks that instantiation to bound is used to obtain the
/// omitted type arguments
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/static_type_helper.dart";

inline class V1<T extends num> {
final int id;
V1(this.id);
}

inline class V2<T extends Object> {
final int id;
V2(this.id);
}

inline class V3<T extends Object?> {
final int id;
V3(this.id);
}

main() {
var v1 = V1(42);
v1.expectStaticType<Exactly<V1<num>>>();

var v2 = V2(42);
v2.expectStaticType<Exactly<V2<Object>>>();

var v3 = V3(42);
v3.expectStaticType<Exactly<V3<Object?>>>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.

// 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.

/// @assertion Assume that T1, .. Ts are types, and V resolves to an inline
/// class declaration of the following form:
///
/// inline class V<X1 extends B1, .. Xs extends Bs> ... {
/// final T id;
/// V(this.id);
///
/// ... // Other members.
/// }
/// ...
/// When s is zero, V<T1, .. Ts> simply stands for V, a non-generic inline type.
/// When s is greater than zero, a raw occurrence V is treated like a raw type:
/// Instantiation to bound is used to obtain the omitted type arguments
///
/// @description Checks that instantiation to bound is used to obtain the
/// omitted type arguments. Test default bound
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";

inline class V1<T> {
final int id;
V1(this.id);

Type get type => T;
}

main() {
var v1 = V1(42);
Expect.equals(dynamic, v1.type);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.

/// @assertion If e is an expression whose static type V is the inline type
/// Inline<T1, .. Ts> and m is the name of a member that V has, a member access
/// like e.m(args) is treated as an invocation of the inline member m on the
/// receiver e according to the inline type Inline and with the actual type
/// arguments T1, ..., Ts, with the actual argument part args.
///
/// @description Checks that a member access `e.m(args)` is treated as an
/// invocation of the inline member m on the receiver `e` according to the
/// inline type `Inline` and with the actual type arguments `T1, ..., Ts`, with
/// the actual argument part `args`.
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/static_type_helper.dart";

inline class V1<T> {
final T id;
V1(this.id);

(Map<K, V>, T) asMap<K, V>() => (<K, V>{}, id);
}

main() {
V1<num> v1 = V1(42);
v1.asMap<String, bool>()
.expectStaticType<Exactly<(Map<String, bool>, num)>>();

V1<String> v2 = V1("42");
v2.asMap<String, String>()
.expectStaticType<Exactly<(Map<String, String>, String)>>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.

/// @assertion Similarly, e.m is treated an invocation of the inline member m on
/// the receiver e according to the inline type Inline and with the actual type
/// arguments T1, ..., Ts and no actual argument part.
///
/// @description Checks that a member access `e.m` is treated as an invocation
/// of the inline member `m` on the receiver `e` according to the inline type
/// `Inline` and with the actual type arguments `T1, ..., Ts` and no actual
/// argument part
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/static_type_helper.dart";

inline class V1<T, K, V> {
final T id;
V1(this.id);

(Map<K, V>, T) get asMap => (<K, V>{}, id);
}

main() {
V1<num, String, bool> v1 = V1(42);
v1.asMap.expectStaticType<Exactly<(Map<String, bool>, num)>>();

V1<String, String, Null> v2 = V1("42");
v2.asMap.expectStaticType<Exactly<(Map<String, Null>, String)>>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.

/// @assertion If e is an expression whose static type V is the inline type
/// Inline<T1, .. Ts> and V has no member whose basename is the basename of m,
/// a member access like e.m(args) may be an extension member access, following
/// the normal rules about applicability and accessibility of extensions, in
/// particular that V must match the on-type of the extension.
///
/// @description Checks that if `V` has no member with the name `m`, but there
/// is an extension member `m` then it is invoked
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";

extension Ex1 on V {
String foo() => "Ex1.foo()";
}

extension Ex2 on int {
String bar() => "Ex2.bar()";
}

inline class V {
final int id;
V(this.id);
}

main() {
V v = V(42);
Expect.equals("Ex1.foo()", v.foo());
Expect.equals("Ex2.bar()", v.id.bar());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.

/// @assertion If e is an expression whose static type V is the inline type
/// Inline<T1, .. Ts> and V has no member whose basename is the basename of m,
/// a member access like e.m(args) may be an extension member access, following
/// the normal rules about applicability and accessibility of extensions, in
/// particular that V must match the on-type of the extension.
///
/// @description Checks that it is a compile-time error if `V` has no member
/// with name `m` and there is no extension member with the name `m`
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

extension Ex1 on V {
String foo() => "Ex1.foo()";
}

extension Ex2 on int {
String bar() => "Ex2.bar()";
}

inline class V {
final int id;
V(this.id);
}

main() {
V v = V(42);
v.bar();
// ^^^
// [analyzer] unspecified
// [cfe] unspecified

v.id.foo();
// ^^^
// [analyzer] unspecified
// [cfe] unspecified
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.

/// @assertion If e is an expression whose static type V is the inline type
/// Inline<T1, .. Ts> and V has no member whose basename is the basename of m,
/// a member access like e.m(args) may be an extension member access, following
/// the normal rules about applicability and accessibility of extensions, in
/// particular that V must match the on-type of the extension.
///
/// @description Checks that if `V` has no member with the name `m`, but there
/// is an extension member `m` then it is invoked
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";

extension Ex1 on V<String> {
String foo() => "Ex1.foo()";
}

extension Ex2 on V<int> {
String foo() => "Ex2.foo()";
}

extension Ex3 on int {
String foo() => "Ex3.foo()";
}

inline class V<T> {
final T id;
V(this.id);
}

main() {
V<String> v1 = V("42");
Expect.equals("Ex1.foo()", v1.foo());

V<int> v2 = V(42);
Expect.equals("Ex2.foo()", v2.foo());
Expect.equals("Ex3.foo()", v2.id.foo());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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.

/// @assertion If e is an expression whose static type V is the inline type
/// Inline<T1, .. Ts> and V has no member whose basename is the basename of m,
/// a member access like e.m(args) may be an extension member access, following
/// the normal rules about applicability and accessibility of extensions, in
/// particular that V must match the on-type of the extension.
///
/// @description Checks that it is a compile-time error if `V` has no member
/// with name `m` and there is no extension member with the name `m`
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

extension Ex1 on V<String> {
String fooString() => "fooString";
}

extension Ex2 on V<int> {
String fooInt() => "fooInt";
}

extension Ex3 on String {
String barString() => "barString";
}

extension Ex4 on int {
String barInt() => "barInt";
}

inline class V<T> {
final T id;
V(this.id);
}

main() {
V<String> v1 = V("42");
v1.fooInt();
// ^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v1.id.fooString();
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v1.barString();
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v1.barInt();
// ^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

V<int> v2 = V(42);
v2.fooString();
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v2.id.fooInt();
// ^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v2.barString();
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified

v2.barInt();
// ^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
}
Loading

0 comments on commit 5ceb054

Please sign in to comment.