From 7e57f6e371d2cd5ea4042c63a04b7b05bda8a096 Mon Sep 17 00:00:00 2001 From: Chloe Stefantsova Date: Tue, 4 Oct 2022 11:41:45 +0000 Subject: [PATCH] [cfe] Implement pointwise implicit downcasts for record literals This CL implements the adjustment of the static semantics for records as described in https://github.com/dart-lang/language/pull/2489/commits/d19f6d564457a1c3108e644e0eb6106b6418f987. The adjustment is based on the discussion at https://github.com/dart-lang/language/issues/2488. Part of https://github.com/dart-lang/sdk/issues/49713 Change-Id: I7a9d456f702ad0fb14aa3bd121ba9d2bbd104414 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262202 Reviewed-by: Johnni Winther Commit-Queue: Chloe Stefantsova --- .../type_inference/inference_results.dart | 19 +++++- .../type_inference/inference_visitor.dart | 66 +++++++++++++------ .../inference_visitor_base.dart | 5 +- .../test/spell_checking_list_common.txt | 3 + .../records/pointwise_implicit_downcasts.dart | 21 ++++++ ...wise_implicit_downcasts.dart.strong.expect | 25 +++++++ ...t_downcasts.dart.strong.transformed.expect | 30 +++++++++ ...icit_downcasts.dart.textual_outline.expect | 7 ++ ...casts.dart.textual_outline_modelled.expect | 8 +++ ...ntwise_implicit_downcasts.dart.weak.expect | 25 +++++++ ...mplicit_downcasts.dart.weak.modular.expect | 25 +++++++ ...mplicit_downcasts.dart.weak.outline.expect | 16 +++++ ...cit_downcasts.dart.weak.transformed.expect | 30 +++++++++ .../testcases/records/simple_inference.dart | 2 +- .../simple_inference.dart.strong.expect | 11 +--- ...e_inference.dart.strong.transformed.expect | 14 +--- .../records/simple_inference.dart.weak.expect | 11 +--- .../simple_inference.dart.weak.modular.expect | 11 +--- ...ple_inference.dart.weak.transformed.expect | 14 +--- 19 files changed, 267 insertions(+), 76 deletions(-) create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline_modelled.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.modular.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.outline.expect create mode 100644 pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.transformed.expect diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_results.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_results.dart index 5c66635c17f..4584be7f553 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/inference_results.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/inference_results.dart @@ -303,7 +303,21 @@ class ExpressionInferenceResult { /// The inferred expression. final Expression expression; - ExpressionInferenceResult(this.inferredType, this.expression) + /// More precise type of the expression after coercion. + /// + /// Consider the following code: + /// + /// dynamic foo = 3; + /// int bar = foo; + /// + /// In the example above `foo` is coerced to `foo as int`, but + /// [inferredType]` of `foo` stays `dynamic`. In some situations, like + /// coercing elements of record literals, we want to know the more precise + /// type of the expression after coercion, `int` in the example above. + final DartType? postCoercionType; + + ExpressionInferenceResult(this.inferredType, this.expression, + {this.postCoercionType = null}) // ignore: unnecessary_null_comparison : assert(expression != null); @@ -416,6 +430,9 @@ class NullAwareExpressionInferenceResult implements ExpressionInferenceResult { 'NullAwareExpressionInferenceResult'); } + @override + DartType? get postCoercionType => null; + @override ExpressionInferenceResult stopShorting() { Expression expression = nullAwareAction; diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart index b6ab581ec58..2256b888a92 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart @@ -7362,7 +7362,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ExpressionInferenceResult visitInternalRecordLiteral( InternalRecordLiteral node, DartType typeContext) { List positional = node.positional; - List named = node.named; + List namedUnsorted = node.named; + List named = namedUnsorted; Map? namedElements = node.namedElements; List originalElementOrder = node.originalElementOrder; List? hoistedExpressions; @@ -7371,19 +7372,23 @@ class InferenceVisitorImpl extends InferenceVisitorBase Map? namedTypeContexts; if (typeContext is RecordType && typeContext.positional.length == positional.length && - typeContext.named.length == named.length) { + typeContext.named.length == namedUnsorted.length) { + namedTypeContexts = {}; + for (NamedType namedType in typeContext.named) { + namedTypeContexts[namedType.name] = namedType.type; + } + bool sameNames = true; - for (int i = 0; sameNames && i < named.length; i++) { - if (typeContext.named[i].name != named[i].name) { + for (int i = 0; sameNames && i < namedUnsorted.length; i++) { + if (!namedTypeContexts.containsKey(namedUnsorted[i].name)) { sameNames = false; } } + if (sameNames) { positionalTypeContexts = typeContext.positional; - namedTypeContexts = {}; - for (NamedType namedType in typeContext.named) { - namedTypeContexts[namedType.name] = namedType.type; - } + } else { + namedTypeContexts = null; } } @@ -7396,9 +7401,18 @@ class InferenceVisitorImpl extends InferenceVisitorBase namedTypes = []; for (int index = 0; index < positional.length; index++) { Expression expression = positional[index]; - ExpressionInferenceResult expressionResult = inferExpression(expression, - positionalTypeContexts?[index] ?? const UnknownType(), true); - positionalTypes.add(expressionResult.inferredType); + + DartType contextType = + positionalTypeContexts?[index] ?? const UnknownType(); + ExpressionInferenceResult expressionResult = + inferExpression(expression, contextType, true); + if (contextType is! UnknownType) { + expressionResult = + ensureAssignableResult(contextType, expressionResult); + } + + positionalTypes.add( + expressionResult.postCoercionType ?? expressionResult.inferredType); positional[index] = expressionResult.expression; } } else { @@ -7436,12 +7450,17 @@ class InferenceVisitorImpl extends InferenceVisitorBase for (int index = originalElementOrder.length - 1; index >= 0; index--) { Object element = originalElementOrder[index]; if (element is NamedExpression) { - ExpressionInferenceResult expressionResult = inferExpression( - element.value, - namedTypeContexts?[element.name] ?? const UnknownType(), - true); + DartType contextType = + namedTypeContexts?[element.name] ?? const UnknownType(); + ExpressionInferenceResult expressionResult = + inferExpression(element.value, contextType, true); + if (contextType is! UnknownType) { + expressionResult = + ensureAssignableResult(contextType, expressionResult); + } Expression expression = expressionResult.expression; - DartType type = expressionResult.inferredType; + DartType type = expressionResult.postCoercionType ?? + expressionResult.inferredType; // TODO(johnniwinther): Should we use [isPureExpression] as is, make // it include (simple) literals, or add a new predicate? if (needsHoisting && !isPureExpression(expression)) { @@ -7462,12 +7481,17 @@ class InferenceVisitorImpl extends InferenceVisitorBase } nameIndex--; } else { - ExpressionInferenceResult expressionResult = inferExpression( - element as Expression, - positionalTypeContexts?[positionalIndex] ?? const UnknownType(), - true); + DartType contextType = + positionalTypeContexts?[positionalIndex] ?? const UnknownType(); + ExpressionInferenceResult expressionResult = + inferExpression(element as Expression, contextType, true); + if (contextType is! UnknownType) { + expressionResult = + ensureAssignableResult(contextType, expressionResult); + } Expression expression = expressionResult.expression; - DartType type = expressionResult.inferredType; + DartType type = expressionResult.postCoercionType ?? + expressionResult.inferredType; // TODO(johnniwinther): Should we use [isPureExpression] as is, make // it include (simple) literals, or add a new predicate? if (needsHoisting && !isPureExpression(expression)) { diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart index 8da6afada7b..eab3dd4ff5c 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart @@ -529,6 +529,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor { DartType expressionType = inferenceResult.inferredType; Expression expression = inferenceResult.expression; Expression result; + DartType? postCoercionType; switch (assignabilityResult.kind) { case AssignabilityKind.assignable: result = expression; @@ -540,6 +541,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor { ..isForNonNullableByDefault = isNonNullableByDefault ..isForDynamic = expressionType is DynamicType ..fileOffset = fileOffset; + postCoercionType = initialContextType; break; case AssignabilityKind.unassignable: // Error: not assignable. Perform error recovery. @@ -624,7 +626,8 @@ abstract class InferenceVisitorBase implements InferenceVisitor { if (!identical(result, expression)) { flowAnalysis.forwardExpression(result, expression); - return new ExpressionInferenceResult(expressionType, result); + return new ExpressionInferenceResult(expressionType, result, + postCoercionType: postCoercionType); } else { return inferenceResult; } diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt index fb577ba0c64..ece25f3244f 100644 --- a/pkg/front_end/test/spell_checking_list_common.txt +++ b/pkg/front_end/test/spell_checking_list_common.txt @@ -491,6 +491,9 @@ closures clue code coerce +coerced +coercing +coercion coincides coinductively collapses diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart new file mode 100644 index 00000000000..9d2e2674e6b --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2022, 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. + +class Callable { + void call() {} +} + +T id(T x) => x; + +foo() { + // No static error. + // Inferred type of the record is (int, double, int Function(int), void Function()). + var c = Callable(); + dynamic d = 3; + (num, double, int Function(int), void Function()) r = (d, 3, id, c); + ({num x, double y, int Function(int) f, void Function() g}) r2 = (x: d, y: 3, f: id, g: c); + (num, double, {int Function(int) f, void Function() g}) r3 = (d, 3, f: id, g: c); +} + +main() {} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.expect new file mode 100644 index 00000000000..555fa6e1385 --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.expect @@ -0,0 +1,25 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + : super core::Object::•() + ; + method call() → void {} +} +static method id(self::id::T% x) → self::id::T% + return x; +static method foo() → dynamic { + self::Callable c = new self::Callable::•(); + dynamic d = 3; + (core::num, core::double, (core::int) → core::int, () → void) r = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, #C2, let final self::Callable #t1 = c in #t1 == null ?{() → void} null : #t1.{self::Callable::call}{() → void}); + ({required f: (core::int) → core::int, required g: () → void, required x: core::num, required y: core::double}) r2 = let final core::num #t2 = d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num in let final core::double #t3 = 3.0 in let final (core::int) → core::int #t4 = #C2 in ({f: #t4, g: let final self::Callable #t5 = c in #t5 == null ?{() → void} null : #t5.{self::Callable::call}{() → void}, x: #t2, y: #t3}); + (core::num, core::double, {required f: (core::int) → core::int, required g: () → void}) r3 = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, {f: #C2, g: let final self::Callable #t6 = c in #t6 == null ?{() → void} null : #t6.{self::Callable::call}{() → void}}); +} +static method main() → dynamic {} + +constants { + #C1 = static-tearoff self::id + #C2 = instantiation #C1 +} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.transformed.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.transformed.expect new file mode 100644 index 00000000000..e8b53f77735 --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.strong.transformed.expect @@ -0,0 +1,30 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + : super core::Object::•() + ; + method call() → void {} +} +static method id(self::id::T% x) → self::id::T% + return x; +static method foo() → dynamic { + self::Callable c = new self::Callable::•(); + dynamic d = 3; + (core::num, core::double, (core::int) → core::int, () → void) r = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, #C2, let final self::Callable #t1 = c in #t1 == null ?{() → void} null : #t1.{self::Callable::call}{() → void}); + ({required f: (core::int) → core::int, required g: () → void, required x: core::num, required y: core::double}) r2 = let final core::num #t2 = d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num in let final core::double #t3 = 3.0 in let final (core::int) → core::int #t4 = #C2 in ({f: #t4, g: let final self::Callable #t5 = c in #t5 == null ?{() → void} null : #t5.{self::Callable::call}{() → void}, x: #t2, y: #t3}); + (core::num, core::double, {required f: (core::int) → core::int, required g: () → void}) r3 = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, {f: #C2, g: let final self::Callable #t6 = c in #t6 == null ?{() → void} null : #t6.{self::Callable::call}{() → void}}); +} +static method main() → dynamic {} + +constants { + #C1 = static-tearoff self::id + #C2 = instantiation #C1 +} + +Extra constant evaluation status: +Evaluated: VariableGet @ org-dartlang-testcase:///pointwise_implicit_downcasts.dart:17:84 -> InstantiationConstant(id) +Evaluated: VariableGet @ org-dartlang-testcase:///pointwise_implicit_downcasts.dart:17:78 -> DoubleConstant(3.0) +Extra constant evaluation: evaluated: 38, effectively constant: 2 diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline.expect new file mode 100644 index 00000000000..fba2365fd27 --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline.expect @@ -0,0 +1,7 @@ +class Callable { + void call() {} +} + +T id(T x) => x; +foo() {} +main() {} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..aab97f0ff7a --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.textual_outline_modelled.expect @@ -0,0 +1,8 @@ +T id(T x) => x; + +class Callable { + void call() {} +} + +foo() {} +main() {} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.expect new file mode 100644 index 00000000000..e48067a688a --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.expect @@ -0,0 +1,25 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + : super core::Object::•() + ; + method call() → void {} +} +static method id(self::id::T% x) → self::id::T% + return x; +static method foo() → dynamic { + self::Callable c = new self::Callable::•(); + dynamic d = 3; + (core::num, core::double, (core::int) → core::int, () → void) r = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, #C2, let final self::Callable #t1 = c in #t1 == null ?{() → void} null : #t1.{self::Callable::call}{() → void}); + ({required f: (core::int) → core::int, required g: () → void, required x: core::num, required y: core::double}) r2 = let final core::num #t2 = d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num in let final core::double #t3 = 3.0 in let final (core::int) → core::int #t4 = #C2 in ({f: #t4, g: let final self::Callable #t5 = c in #t5 == null ?{() → void} null : #t5.{self::Callable::call}{() → void}, x: #t2, y: #t3}); + (core::num, core::double, {required f: (core::int) → core::int, required g: () → void}) r3 = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, {f: #C2, g: let final self::Callable #t6 = c in #t6 == null ?{() → void} null : #t6.{self::Callable::call}{() → void}}); +} +static method main() → dynamic {} + +constants { + #C1 = static-tearoff self::id + #C2 = instantiation #C1 +} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.modular.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.modular.expect new file mode 100644 index 00000000000..e48067a688a --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.modular.expect @@ -0,0 +1,25 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + : super core::Object::•() + ; + method call() → void {} +} +static method id(self::id::T% x) → self::id::T% + return x; +static method foo() → dynamic { + self::Callable c = new self::Callable::•(); + dynamic d = 3; + (core::num, core::double, (core::int) → core::int, () → void) r = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, #C2, let final self::Callable #t1 = c in #t1 == null ?{() → void} null : #t1.{self::Callable::call}{() → void}); + ({required f: (core::int) → core::int, required g: () → void, required x: core::num, required y: core::double}) r2 = let final core::num #t2 = d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num in let final core::double #t3 = 3.0 in let final (core::int) → core::int #t4 = #C2 in ({f: #t4, g: let final self::Callable #t5 = c in #t5 == null ?{() → void} null : #t5.{self::Callable::call}{() → void}, x: #t2, y: #t3}); + (core::num, core::double, {required f: (core::int) → core::int, required g: () → void}) r3 = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, {f: #C2, g: let final self::Callable #t6 = c in #t6 == null ?{() → void} null : #t6.{self::Callable::call}{() → void}}); +} +static method main() → dynamic {} + +constants { + #C1 = static-tearoff self::id + #C2 = instantiation #C1 +} diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.outline.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.outline.expect new file mode 100644 index 00000000000..a62758ba83a --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.outline.expect @@ -0,0 +1,16 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + ; + method call() → void + ; +} +static method id(self::id::T% x) → self::id::T% + ; +static method foo() → dynamic + ; +static method main() → dynamic + ; diff --git a/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.transformed.expect b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.transformed.expect new file mode 100644 index 00000000000..35f9e471ecd --- /dev/null +++ b/pkg/front_end/testcases/records/pointwise_implicit_downcasts.dart.weak.transformed.expect @@ -0,0 +1,30 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; + +class Callable extends core::Object { + synthetic constructor •() → self::Callable + : super core::Object::•() + ; + method call() → void {} +} +static method id(self::id::T% x) → self::id::T% + return x; +static method foo() → dynamic { + self::Callable c = new self::Callable::•(); + dynamic d = 3; + (core::num, core::double, (core::int) → core::int, () → void) r = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, #C2, let final self::Callable #t1 = c in #t1 == null ?{() → void} null : #t1.{self::Callable::call}{() → void}); + ({required f: (core::int) → core::int, required g: () → void, required x: core::num, required y: core::double}) r2 = let final core::num #t2 = d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num in let final core::double #t3 = 3.0 in let final (core::int) → core::int #t4 = #C2 in ({f: #t4, g: let final self::Callable #t5 = c in #t5 == null ?{() → void} null : #t5.{self::Callable::call}{() → void}, x: #t2, y: #t3}); + (core::num, core::double, {required f: (core::int) → core::int, required g: () → void}) r3 = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.0, {f: #C2, g: let final self::Callable #t6 = c in #t6 == null ?{() → void} null : #t6.{self::Callable::call}{() → void}}); +} +static method main() → dynamic {} + +constants { + #C1 = static-tearoff self::id + #C2 = instantiation #C1 +} + +Extra constant evaluation status: +Evaluated: VariableGet @ org-dartlang-testcase:///pointwise_implicit_downcasts.dart:17:84 -> InstantiationConstant(id) +Evaluated: VariableGet @ org-dartlang-testcase:///pointwise_implicit_downcasts.dart:17:78 -> DoubleConstant(3.0) +Extra constant evaluation: evaluated: 38, effectively constant: 2 diff --git a/pkg/front_end/testcases/records/simple_inference.dart b/pkg/front_end/testcases/records/simple_inference.dart index da9d76a4d82..8f3c99bf573 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart +++ b/pkg/front_end/testcases/records/simple_inference.dart @@ -15,7 +15,7 @@ foo3() { } foo4() { - (num, num) r = (3 as dynamic, 3.5); // Error. + (num, num) r = (3 as dynamic, 3.5); } foo5((int, String?) r, (int, X) Function() f) { diff --git a/pkg/front_end/testcases/records/simple_inference.dart.strong.expect b/pkg/front_end/testcases/records/simple_inference.dart.strong.expect index 51b70beb25c..bc3c922a323 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart.strong.expect +++ b/pkg/front_end/testcases/records/simple_inference.dart.strong.expect @@ -1,11 +1,4 @@ library /*isNonNullableByDefault*/; -// -// Problems in library: -// -// pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. -// (num, num) r = (3 as dynamic, 3.5); // Error. -// ^ -// import self as self; import "dart:core" as core; @@ -31,9 +24,7 @@ static method foo3() → dynamic { } =>#t1; } static method foo4() → dynamic { - (core::num, core::num) r = invalid-expression "pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. - (num, num) r = (3 as dynamic, 3.5); // Error. - ^" in (3 as{ForNonNullableByDefault} dynamic, 3.5) as{TypeError,ForNonNullableByDefault} (core::num, core::num); + (core::num, core::num) r = ((3 as{ForNonNullableByDefault} dynamic) as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.5); } static method foo5((core::int, core::String?) r, () → (core::int, X%) f) → dynamic { r = f(){() → (core::int, core::String?)}; diff --git a/pkg/front_end/testcases/records/simple_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/records/simple_inference.dart.strong.transformed.expect index f44bae4479c..60d1614abf8 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/records/simple_inference.dart.strong.transformed.expect @@ -1,11 +1,4 @@ library /*isNonNullableByDefault*/; -// -// Problems in library: -// -// pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. -// (num, num) r = (3 as dynamic, 3.5); // Error. -// ^ -// import self as self; import "dart:core" as core; @@ -31,9 +24,7 @@ static method foo3() → dynamic { } =>#t1; } static method foo4() → dynamic { - (core::num, core::num) r = invalid-expression "pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. - (num, num) r = (3 as dynamic, 3.5); // Error. - ^" in (3 as{ForNonNullableByDefault} dynamic, 3.5) as{TypeError,ForNonNullableByDefault} (core::num, core::num); + (core::num, core::num) r = ((3 as{ForNonNullableByDefault} dynamic) as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.5); } static method foo5((core::int, core::String?) r, () → (core::int, X%) f) → dynamic { r = f(){() → (core::int, core::String?)}; @@ -53,4 +44,5 @@ Extra constant evaluation status: Evaluated: RecordLiteral @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) Evaluated: VariableGetImpl @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) Evaluated: VariableGet @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) -Extra constant evaluation: evaluated: 24, effectively constant: 3 +Evaluated: RecordLiteral @ org-dartlang-testcase:///simple_inference.dart:18:18 -> RecordConstant(const (3, 3.5)) +Extra constant evaluation: evaluated: 25, effectively constant: 4 diff --git a/pkg/front_end/testcases/records/simple_inference.dart.weak.expect b/pkg/front_end/testcases/records/simple_inference.dart.weak.expect index 51b70beb25c..bc3c922a323 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart.weak.expect +++ b/pkg/front_end/testcases/records/simple_inference.dart.weak.expect @@ -1,11 +1,4 @@ library /*isNonNullableByDefault*/; -// -// Problems in library: -// -// pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. -// (num, num) r = (3 as dynamic, 3.5); // Error. -// ^ -// import self as self; import "dart:core" as core; @@ -31,9 +24,7 @@ static method foo3() → dynamic { } =>#t1; } static method foo4() → dynamic { - (core::num, core::num) r = invalid-expression "pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. - (num, num) r = (3 as dynamic, 3.5); // Error. - ^" in (3 as{ForNonNullableByDefault} dynamic, 3.5) as{TypeError,ForNonNullableByDefault} (core::num, core::num); + (core::num, core::num) r = ((3 as{ForNonNullableByDefault} dynamic) as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.5); } static method foo5((core::int, core::String?) r, () → (core::int, X%) f) → dynamic { r = f(){() → (core::int, core::String?)}; diff --git a/pkg/front_end/testcases/records/simple_inference.dart.weak.modular.expect b/pkg/front_end/testcases/records/simple_inference.dart.weak.modular.expect index 51b70beb25c..bc3c922a323 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart.weak.modular.expect +++ b/pkg/front_end/testcases/records/simple_inference.dart.weak.modular.expect @@ -1,11 +1,4 @@ library /*isNonNullableByDefault*/; -// -// Problems in library: -// -// pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. -// (num, num) r = (3 as dynamic, 3.5); // Error. -// ^ -// import self as self; import "dart:core" as core; @@ -31,9 +24,7 @@ static method foo3() → dynamic { } =>#t1; } static method foo4() → dynamic { - (core::num, core::num) r = invalid-expression "pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. - (num, num) r = (3 as dynamic, 3.5); // Error. - ^" in (3 as{ForNonNullableByDefault} dynamic, 3.5) as{TypeError,ForNonNullableByDefault} (core::num, core::num); + (core::num, core::num) r = ((3 as{ForNonNullableByDefault} dynamic) as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.5); } static method foo5((core::int, core::String?) r, () → (core::int, X%) f) → dynamic { r = f(){() → (core::int, core::String?)}; diff --git a/pkg/front_end/testcases/records/simple_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/records/simple_inference.dart.weak.transformed.expect index f44bae4479c..60d1614abf8 100644 --- a/pkg/front_end/testcases/records/simple_inference.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/records/simple_inference.dart.weak.transformed.expect @@ -1,11 +1,4 @@ library /*isNonNullableByDefault*/; -// -// Problems in library: -// -// pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. -// (num, num) r = (3 as dynamic, 3.5); // Error. -// ^ -// import self as self; import "dart:core" as core; @@ -31,9 +24,7 @@ static method foo3() → dynamic { } =>#t1; } static method foo4() → dynamic { - (core::num, core::num) r = invalid-expression "pkg/front_end/testcases/records/simple_inference.dart:18:18: Error: A value of type '(dynamic, double)' can't be assigned to a variable of type '(num, num)'. - (num, num) r = (3 as dynamic, 3.5); // Error. - ^" in (3 as{ForNonNullableByDefault} dynamic, 3.5) as{TypeError,ForNonNullableByDefault} (core::num, core::num); + (core::num, core::num) r = ((3 as{ForNonNullableByDefault} dynamic) as{TypeError,ForDynamic,ForNonNullableByDefault} core::num, 3.5); } static method foo5((core::int, core::String?) r, () → (core::int, X%) f) → dynamic { r = f(){() → (core::int, core::String?)}; @@ -53,4 +44,5 @@ Extra constant evaluation status: Evaluated: RecordLiteral @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) Evaluated: VariableGetImpl @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) Evaluated: VariableGet @ org-dartlang-testcase:///simple_inference.dart:14:18 -> RecordConstant(const (3, 3.5)) -Extra constant evaluation: evaluated: 24, effectively constant: 3 +Evaluated: RecordLiteral @ org-dartlang-testcase:///simple_inference.dart:18:18 -> RecordConstant(const (3, 3.5)) +Extra constant evaluation: evaluated: 25, effectively constant: 4