159de518e2
Change-Id: I28f61e1e85408acc5403bfe95f360df4c7cb5ece Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425151 Auto-Submit: Bob Nystrom <rnystrom@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
168 lines
5.6 KiB
Dart
168 lines
5.6 KiB
Dart
// Copyright (c) 2024, 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.
|
|
|
|
// Verifies that pattern type schemas produced by the implementation correspond
|
|
// to the specification in
|
|
// https://github.com/dart-lang/language/blob/main/accepted/3.0/patterns/feature-specification.md#pattern-context-type-schema.
|
|
|
|
import 'package:expect/static_type_helper.dart';
|
|
|
|
test() {
|
|
// The context type schema for a pattern `p` is:
|
|
|
|
// - Logical-and: The greatest lower bound of the context type schemas of the
|
|
// branches.
|
|
{
|
|
var (void Function(int) x && void Function(double) y) = contextType(
|
|
(n) => n.expectStaticType<Exactly<num>>(),
|
|
)..expectStaticType<Exactly<void Function(num)>>();
|
|
}
|
|
|
|
// - Null-assert: A context type schema `E?` where `E` is the context type
|
|
// schema of the inner pattern.
|
|
{
|
|
var ((int i)!) = contextType(1)..expectStaticType<Exactly<int?>>();
|
|
}
|
|
|
|
// - Variable:
|
|
//
|
|
// i. If `p` has a type annotation, the context type schema is the annotated
|
|
// type.
|
|
{
|
|
var (int i) = contextType(1)..expectStaticType<Exactly<int>>();
|
|
}
|
|
|
|
// ii. Else the context type schema is _.
|
|
//
|
|
// This rule is actually never used, because:
|
|
// - Pattern type schemas are only computed for pattern variable
|
|
// declarations and pattern assignments.
|
|
// - It is a compile-time error if a variable pattern appears in an
|
|
// assignment context. So the context type schema for a variable pattern
|
|
// only matters if it appears in a declaration context.
|
|
// - It is a compile-time error if a variable pattern in a declaration
|
|
// context is marked with `var` or `final`. So a variable pattern inside a
|
|
// pattern variable declaration must have a type annotation.
|
|
|
|
// - Identifier:
|
|
//
|
|
// i. In an assignment context, the context type schema is the static type
|
|
// of the variable that `p` resolves to.
|
|
{
|
|
int i;
|
|
(i) = contextType(1)..expectStaticType<Exactly<int>>();
|
|
}
|
|
|
|
// ii. Else the context type schema is `_`.
|
|
{
|
|
var [x] = [1]..expectStaticType<Exactly<List<int>>>();
|
|
var [_] = [1]..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// - Cast: The context type schema is `_`.
|
|
{
|
|
var [_ as Object] = [1]..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// - Parenthesized: The context type schema of the inner subpattern.
|
|
{
|
|
var (<int>[]) = contextType(<int>[])
|
|
..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// - List: A context type schema `List<E>` where:
|
|
//
|
|
// i. If `p` has a type argument, then `E` is the type argument.
|
|
{
|
|
var <int>[] = contextType(<int>[])..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// ii. Else if `p` has no elements then `E` is `_`.
|
|
{
|
|
var [] = [1]
|
|
..expectStaticType<Exactly<List<int>>>()
|
|
..removeLast();
|
|
}
|
|
|
|
// iii. Else, infer the type schema from the elements:
|
|
//
|
|
// a. Let `es` be an empty list of type schemas.
|
|
//
|
|
// b. For each element `e` in `p`:
|
|
//
|
|
// a. If `e` is a matching rest element with subpattern `s` and the
|
|
// context type schema of `s` is an `Iterable<T>` for some type
|
|
// schema `T`, then add `T` to es.
|
|
{
|
|
var [...Iterable<int> x] = contextType(<int>[])
|
|
..expectStaticType<Exactly<List<int>>>();
|
|
var [...List<int> y] = contextType(<int>[])
|
|
..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// b. Else if `e` is not a rest element, add the context type schema
|
|
// of `e` to `es`.
|
|
{
|
|
var [int x] = contextType(<int>[0])..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// c. If `es` is empty, then `E` is `_`.
|
|
{
|
|
var [...] = [1]..expectStaticType<Exactly<List<int>>>();
|
|
var [...Object x] = [1]..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// d. Else `E` is the greatest lower bound of the type schemas in `es`.
|
|
{
|
|
var [void Function(int) x, void Function(double) y] = contextType([
|
|
(n) => n.expectStaticType<Exactly<num>>(),
|
|
(n) => n.expectStaticType<Exactly<num>>(),
|
|
])..expectStaticType<Exactly<List<void Function(num)>>>();
|
|
}
|
|
|
|
// - Map: A type schema `Map<K, V>` where:
|
|
//
|
|
// i. If `p` has type arguments then `K`, and `V` are those type arguments.
|
|
{
|
|
var <int, String>{0: _} = contextType(<int, String>{0: 'x'})
|
|
..expectStaticType<Exactly<Map<int, String>>>();
|
|
}
|
|
|
|
// ii. Else `K` is `_` and `V` is the greatest lower bound of the context
|
|
// type schemas of all value subpatterns.
|
|
{
|
|
var {1: void Function(int) x, 2: void Function(double) y} = {
|
|
(1 as num): (n) => n.expectStaticType<Exactly<num>>(),
|
|
(2 as num): (n) => n.expectStaticType<Exactly<num>>(),
|
|
}..expectStaticType<Exactly<Map<num, void Function(num)>>>();
|
|
}
|
|
|
|
// Record: A record type schema with positional and named fields corresponding
|
|
// to the type schemas of the corresponding field subpatterns.
|
|
{
|
|
var (int _, y: String _) = contextType((1, y: 'y'))
|
|
..expectStaticType<Exactly<(int, {String y})>>();
|
|
}
|
|
|
|
// Object: The type the object name resolves to.
|
|
{
|
|
var List<int>() = contextType(<int>[])
|
|
..expectStaticType<Exactly<List<int>>>();
|
|
}
|
|
|
|
// If the type the object name resolves to is generic, and no type arguments
|
|
// are specified, then instantiate to bounds is used to fill in provisional
|
|
// type arguments for the purpose of determining the context type schema.
|
|
{
|
|
var List(first: x) = contextType([1])
|
|
..expectStaticType<Exactly<List<dynamic>>>();
|
|
var List(first: y) = <int>[1];
|
|
y.expectStaticType<Exactly<int>>();
|
|
}
|
|
}
|
|
|
|
main() {
|
|
test();
|
|
}
|