mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:09:49 +00:00
3636c8a08b
According to the patterns spec, the pattern context type schema for a cast pattern should be `_`. What was actually implemented was `Object?`. This is unlikely to make a difference in practice, since (a) cast patterns are unlikely to be used in circumstances where the pattern context type schema makes a difference, and (b) it takes some effort to come up with expressions whose type inference behavior is differenc between a schema of `Object?` and a schema of `_`. Change-Id: I695752c8c163621a34faaa8d62b2b076c8152eb0 Bug: https://github.com/dart-lang/sdk/issues/54640 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346383 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
172 lines
5.6 KiB
Dart
172 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 '../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();
|
|
}
|