Implement int-to-double literal conversion.

The implementation strategy is to replace int literals with double
literals during type inference, provided they occur in a double
context and can be represented exactly as a double.  This requires us
to keep integer literals larger than the 64-bit range until after type
inference and to keep the source text of 64-bit integers until after
type inference for error reporting.

We postpone the check for web int literals as well because the
expression generator that was performing it isn't otherwise needed.

Fixes https://github.com/dart-lang/sdk/issues/34357.

Change-Id: Ia78c031565cad83961675fc4fb1cc871eaed01d3
Reviewed-on: https://dart-review.googlesource.com/c/78122
Commit-Queue: Kevin Millikin <kmillikin@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
This commit is contained in:
Kevin Millikin 2018-10-09 09:15:28 +00:00 committed by commit-bot@chromium.org
parent 79e8b3d57f
commit 4e4e9ec74a
19 changed files with 325 additions and 279 deletions

View file

@ -4324,30 +4324,30 @@ Message _withArgumentsInputFileNotFound(Uri uri_) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
Token
token)> templateIntegerLiteralIsOutOfRange = const Template<
Message Function(Token token)>(
String
string)> templateIntegerLiteralIsOutOfRange = const Template<
Message Function(String string)>(
messageTemplate:
r"""The integer literal #lexeme can't be represented in 64 bits.""",
r"""The integer literal #string can't be represented in 64 bits.""",
tipTemplate:
r"""Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
withArguments: _withArgumentsIntegerLiteralIsOutOfRange);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(Token token)> codeIntegerLiteralIsOutOfRange =
const Code<Message Function(Token token)>(
const Code<Message Function(String string)> codeIntegerLiteralIsOutOfRange =
const Code<Message Function(String string)>(
"IntegerLiteralIsOutOfRange", templateIntegerLiteralIsOutOfRange,
analyzerCodes: <String>["INTEGER_LITERAL_OUT_OF_RANGE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsIntegerLiteralIsOutOfRange(Token token) {
String lexeme = token.lexeme;
Message _withArgumentsIntegerLiteralIsOutOfRange(String string) {
if (string.isEmpty) throw 'No string provided';
return new Message(codeIntegerLiteralIsOutOfRange,
message:
"""The integer literal ${lexeme} can't be represented in 64 bits.""",
"""The integer literal ${string} can't be represented in 64 bits.""",
tip:
"""Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
arguments: {'token': token});
arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.

View file

@ -75,7 +75,6 @@ import 'expression_generator.dart'
IncompletePropertyAccessGenerator,
IncompleteSendGenerator,
IndexedAccessGenerator,
IntAccessGenerator,
LoadLibraryGenerator,
ParenthesizedExpressionGenerator,
ParserErrorGenerator,
@ -1140,8 +1139,20 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
@override
void handleParenthesizedExpression(Token token) {
debugEvent("ParenthesizedExpression");
push(new ParenthesizedExpressionGenerator(
this, token.endGroup, popForValue()));
Expression value = popForValue();
if (value is ShadowLargeIntLiteral) {
// We need to know that the expression was parenthesized because we will
// treat -n differently from -(n). If the expression occurs in a double
// context, -n is a double literal and -(n) is an application of unary- to
// an integer literal. And in any other context, '-' is part of the
// syntax of -n, i.e., -9223372036854775808 is OK and it is the minimun
// 64-bit integer, and '-' is an application of unary- in -(n), i.e.,
// -(9223372036854775808) is an error because the literal does not fit in
// 64-bits.
push(value..isParenthesized = true);
} else {
push(new ParenthesizedExpressionGenerator(this, token.endGroup, value));
}
}
@override
@ -1831,7 +1842,23 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
@override
void handleLiteralInt(Token token) {
debugEvent("LiteralInt");
push(IntAccessGenerator.parseIntLiteral(this, token));
int value = int.tryParse(token.lexeme);
if (!library.loader.target.strongMode) {
if (value == null) {
push(unhandled(
'large integer', 'handleLiteralInt', token.charOffset, uri));
} else {
push(forest.literalInt(value, token));
}
return;
}
// Postpone parsing of literals resulting in a negative value
// (hex literals >= 2^63). These are only allowed when not negated.
if (value == null || value < 0) {
push(forest.literalLargeInt(token.lexeme, token));
} else {
push(forest.literalInt(value, token));
}
}
@override
@ -2827,19 +2854,13 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
Expression receiverValue;
if (optional("-", token)) {
operator = "unary-";
if (receiver is IntAccessGenerator) {
receiverValue = receiver.buildNegatedRead();
}
}
bool isSuper = false;
if (receiverValue == null) {
if (receiver is ThisAccessGenerator && receiver.isSuper) {
isSuper = true;
receiverValue = forest.thisExpression(receiver.token);
} else {
receiverValue = toValue(receiver);
}
if (receiver is ThisAccessGenerator && receiver.isSuper) {
isSuper = true;
receiverValue = forest.thisExpression(receiver.token);
} else {
receiverValue = toValue(receiver);
}
push(buildMethodInvocation(receiverValue, new Name(operator),
forest.argumentsEmpty(noLocation), token.charOffset,

View file

@ -22,12 +22,10 @@ import '../fasta_codes.dart'
noLength,
templateCantUseDeferredPrefixAsConstant,
templateDeferredTypeAnnotation,
templateIntegerLiteralIsOutOfRange,
templateMissingExplicitTypeArguments,
templateNotAPrefixInTypeAnnotation,
templateNotAType,
templateUnresolvedPrefixInTypeAnnotation,
templateWebLiteralCannotBeRepresentedExactly;
templateUnresolvedPrefixInTypeAnnotation;
import '../names.dart'
show
@ -667,96 +665,6 @@ abstract class ReadOnlyAccessGenerator implements Generator {
String get debugName => "ReadOnlyAccessGenerator";
}
abstract class IntAccessGenerator implements Generator {
factory IntAccessGenerator(ExpressionGeneratorHelper helper, Token token) {
return helper.forest.intAccessGenerator(helper, token);
}
// TODO(ahe): This should probably be calling unhandled.
@override
String get plainNameForRead => null;
@override
String get debugName => "IntAccessGenerator";
static void checkWebIntLiteralsErrorIfUnexact(
ExpressionGeneratorHelper helper, int value, Token token) {
if (value >= 0 && value <= (1 << 53)) return;
if (!helper.library.loader.target.backendTarget
.errorOnUnexactWebIntLiterals) return;
BigInt asInt = new BigInt.from(value).toUnsigned(64);
BigInt asDouble = new BigInt.from(asInt.toDouble());
if (asInt != asDouble) {
String nearest;
if (token.lexeme.startsWith("0x") || token.lexeme.startsWith("0X")) {
nearest = '0x${asDouble.toRadixString(16)}';
} else {
nearest = '$asDouble';
}
helper.addProblem(
templateWebLiteralCannotBeRepresentedExactly.withArguments(
token.lexeme, nearest),
token.charOffset,
token.charCount);
}
}
static Object parseIntLiteral(ExpressionGeneratorHelper helper, Token token) {
int value = int.tryParse(token.lexeme);
// Postpone parsing of literals resulting in a negative value
// (hex literals >= 2^63). These are only allowed when not negated.
if (value == null || value < 0) {
return new IntAccessGenerator(helper, token);
} else {
checkWebIntLiteralsErrorIfUnexact(helper, value, token);
return helper.forest.literalInt(value, token);
}
}
Expression parseOrError(String literal, Token token) {
int value = int.tryParse(literal);
if (value != null) {
checkWebIntLiteralsErrorIfUnexact(helper, value, token);
return helper.forest.literalInt(value, token);
} else {
return buildError();
}
}
@override
Expression buildSimpleRead() {
// Called when literal that previously failed to parse, or resulted in
// a negative value (hex literals >= 2^63), is not negated.
// Try parsing again, this time accepting negative values.
return parseOrError(token.lexeme, token);
}
Expression buildNegatedRead() {
// Called when literal that previously failed to parse, or resulted in
// a negative value (hex literals >= 2^63), is negated.
// Try parsing with a '-' in front.
return parseOrError("-" + token.lexeme, token);
}
SyntheticExpressionJudgment buildError() {
return helper.buildProblem(
templateIntegerLiteralIsOutOfRange.withArguments(token),
offsetForToken(token),
lengthForToken(token));
}
@override
Expression doInvocation(int offset, Arguments arguments) {
return buildError();
}
@override
void printOn(StringSink sink) {
sink.write(", lexeme: ");
sink.write(token.lexeme);
}
}
abstract class ErroneousExpressionGenerator implements Generator {
/// Pass [arguments] that must be evaluated before throwing an error. At
/// most one of [isGetter] and [isSetter] should be true and they're passed

View file

@ -44,7 +44,6 @@ import 'kernel_expression_generator.dart'
KernelDelayedAssignment,
KernelDelayedPostfixIncrement,
KernelIndexedAccessGenerator,
KernelIntAccessGenerator,
KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelParserErrorGenerator,
@ -95,6 +94,7 @@ import 'kernel_shadow_ast.dart'
NullJudgment,
RethrowJudgment,
ReturnJudgment,
ShadowLargeIntLiteral,
StringConcatenationJudgment,
StringLiteralJudgment,
SymbolLiteralJudgment,
@ -170,7 +170,13 @@ class Fangorn extends Forest {
@override
IntJudgment literalInt(int value, Token token) {
return new IntJudgment(value)..fileOffset = offsetForToken(token);
return new IntJudgment(value, token?.lexeme)
..fileOffset = offsetForToken(token);
}
@override
ShadowLargeIntLiteral literalLargeInt(String literal, Token token) {
return new ShadowLargeIntLiteral(literal, offsetForToken(token));
}
@override
@ -698,12 +704,6 @@ class Fangorn extends Forest {
helper, token, expression, plainNameForRead);
}
@override
KernelIntAccessGenerator intAccessGenerator(
ExpressionGeneratorHelper helper, Token token) {
return new KernelIntAccessGenerator(helper, token);
}
@override
KernelUnresolvedNameGenerator unresolvedNameGenerator(
ExpressionGeneratorHelper helper, Token token, Name name) {

View file

@ -89,6 +89,8 @@ abstract class Forest {
/// literal has the given [value].
Expression literalInt(int value, Token location);
Expression literalLargeInt(String literal, Token location);
/// Return a representation of a list literal. The [constKeyword] is the
/// location of the `const` keyword, or `null` if there is no keyword. The
/// [isConst] is `true` if the literal is either explicitly or implicitly a
@ -390,9 +392,6 @@ abstract class Forest {
Generator readOnlyAccessGenerator(ExpressionGeneratorHelper helper,
Token location, Expression expression, String plainNameForRead);
Generator intAccessGenerator(
ExpressionGeneratorHelper helper, Token location);
Generator unresolvedNameGenerator(
ExpressionGeneratorHelper helper, Token location, Name name);

View file

@ -113,6 +113,7 @@ export 'kernel_shadow_ast.dart'
RedirectingInitializerJudgment,
RethrowJudgment,
ReturnJudgment,
ShadowLargeIntLiteral,
StaticAssignmentJudgment,
StaticGetJudgment,
StaticInvocationJudgment,

View file

@ -49,7 +49,6 @@ import 'expression_generator.dart'
ExpressionGenerator,
Generator,
IndexedAccessGenerator,
IntAccessGenerator,
LoadLibraryGenerator,
NullAwarePropertyAccessGenerator,
ParserErrorGenerator,
@ -1398,31 +1397,6 @@ class KernelReadOnlyAccessGenerator extends KernelGenerator
}
}
class KernelIntAccessGenerator extends KernelGenerator with IntAccessGenerator {
KernelIntAccessGenerator(ExpressionGeneratorHelper helper, Token token)
: super(helper, token);
@override
Expression _makeSimpleRead() => buildError();
@override
Expression _makeSimpleWrite(Expression value, bool voidContext,
ComplexAssignmentJudgment complexAssignment) {
return buildError();
}
@override
Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
return buildError();
}
@override
Expression _makeWrite(Expression value, bool voidContext,
ComplexAssignmentJudgment complexAssignment) {
return buildError();
}
}
class KernelUnresolvedNameGenerator extends KernelGenerator
with ErroneousExpressionGenerator, UnresolvedNameGenerator {
@override

View file

@ -44,7 +44,9 @@ import '../fasta_codes.dart'
templateCantUseSuperBoundedTypeForInstanceCreation,
templateForInLoopElementTypeNotAssignable,
templateForInLoopTypeNotIterable,
templateSwitchExpressionNotAssignable;
templateIntegerLiteralIsOutOfRange,
templateSwitchExpressionNotAssignable,
templateWebLiteralCannotBeRepresentedExactly;
import '../problems.dart' show unhandled, unsupported;
@ -804,7 +806,7 @@ class DoubleJudgment extends DoubleLiteral implements ExpressionJudgment {
/// Common base class for shadow objects representing expressions in kernel
/// form.
abstract class ExpressionJudgment implements Expression {
abstract class ExpressionJudgment extends Expression {
DartType inferredType;
/// Calls back to [inferrer] to perform type inference for whatever concrete
@ -1381,14 +1383,120 @@ abstract class InitializerJudgment implements Initializer {
void infer(ShadowTypeInferrer inferrer);
}
Expression checkWebIntLiteralsErrorIfUnexact(
ShadowTypeInferrer inferrer, int value, String literal, int charOffset) {
if (value >= 0 && value <= (1 << 53)) return null;
if (inferrer.library == null) return null;
if (!inferrer.library.loader.target.backendTarget
.errorOnUnexactWebIntLiterals) return null;
BigInt asInt = BigInt.from(value).toUnsigned(64);
BigInt asDouble = BigInt.from(asInt.toDouble());
if (asInt == asDouble) return null;
String text = literal ?? value.toString();
String nearest = text.startsWith('0x') || text.startsWith('0X')
? '0x${asDouble.toRadixString(16)}'
: asDouble.toString();
int length = literal?.length ?? noLength;
return inferrer.helper
.buildProblem(
templateWebLiteralCannotBeRepresentedExactly.withArguments(
text, nearest),
charOffset,
length)
.desugared;
}
/// Concrete shadow object representing an integer literal in kernel form.
class IntJudgment extends IntLiteral implements ExpressionJudgment {
DartType inferredType;
final String literal;
IntJudgment(int value) : super(value);
IntJudgment(int value, this.literal) : super(value);
double asDouble({bool negated: false}) {
if (value == 0 && negated) return -0.0;
BigInt intValue = BigInt.from(negated ? -value : value);
double doubleValue = intValue.toDouble();
return intValue == BigInt.from(doubleValue) ? doubleValue : null;
}
@override
Expression infer(ShadowTypeInferrer inferrer, DartType typeContext) {
if (inferrer.isDoubleContext(typeContext)) {
double doubleValue = asDouble();
if (doubleValue != null) {
parent.replaceChild(
this, DoubleLiteral(doubleValue)..fileOffset = fileOffset);
inferredType = inferrer.coreTypes.doubleClass.rawType;
return null;
}
}
Expression error =
checkWebIntLiteralsErrorIfUnexact(inferrer, value, literal, fileOffset);
if (error != null) {
parent.replaceChild(this, error);
inferredType = const BottomType();
return null;
}
inferredType = inferrer.coreTypes.intClass.rawType;
return null;
}
}
class ShadowLargeIntLiteral extends IntLiteral implements ExpressionJudgment {
final String literal;
final int fileOffset;
bool isParenthesized = false;
DartType inferredType;
ShadowLargeIntLiteral(this.literal, this.fileOffset) : super(0);
double asDouble({bool negated: false}) {
BigInt intValue = BigInt.tryParse(negated ? '-${literal}' : literal);
if (intValue == null) return null;
double doubleValue = intValue.toDouble();
return !doubleValue.isNaN &&
!doubleValue.isInfinite &&
intValue == BigInt.from(doubleValue)
? doubleValue
: null;
}
int asInt64({bool negated: false}) {
return int.tryParse(negated ? '-${literal}' : literal);
}
@override
Expression infer(ShadowTypeInferrer inferrer, DartType typeContext) {
if (inferrer.isDoubleContext(typeContext)) {
double doubleValue = asDouble();
if (doubleValue != null) {
parent.replaceChild(
this, DoubleLiteral(doubleValue)..fileOffset = fileOffset);
inferredType = inferrer.coreTypes.doubleClass.rawType;
return null;
}
}
int intValue = asInt64();
if (intValue == null) {
Expression replacement = inferrer.helper.buildProblem(
templateIntegerLiteralIsOutOfRange.withArguments(literal),
fileOffset,
literal.length);
parent.replaceChild(this, replacement);
inferredType = const BottomType();
return null;
}
Expression error = checkWebIntLiteralsErrorIfUnexact(
inferrer, intValue, literal, fileOffset);
if (error != null) {
parent.replaceChild(this, error);
inferredType = const BottomType();
return null;
}
parent.replaceChild(this, IntLiteral(intValue)..fileOffset = fileOffset);
inferredType = inferrer.coreTypes.intClass.rawType;
return null;
}
@ -1743,6 +1851,75 @@ class MethodInvocationJudgment extends MethodInvocation
@override
Expression infer(ShadowTypeInferrer inferrer, DartType typeContext) {
if (name.name == 'unary-' &&
arguments.types.isEmpty &&
arguments.positional.isEmpty &&
arguments.named.isEmpty) {
// Replace integer literals in a double context with the corresponding
// double literal if it's exact. For double literals, the negation is
// folded away. In any non-double context, or if there is no exact
// double value, then the corresponding integer literal is left. The
// negation is not folded away so that platforms with web literals can
// distinguish between (non-negated) 0x8000000000000000 represented as
// integer literal -9223372036854775808 which should be a positive number,
// and negated 9223372036854775808 represented as
// -9223372036854775808.unary-() which should be a negative number.
if (receiver is IntJudgment) {
IntJudgment receiver = this.receiver;
if (inferrer.isDoubleContext(typeContext)) {
double doubleValue = receiver.asDouble(negated: true);
if (doubleValue != null) {
parent.replaceChild(
this, DoubleLiteral(doubleValue)..fileOffset = fileOffset);
inferredType = inferrer.coreTypes.doubleClass.rawType;
return null;
}
}
Expression error = checkWebIntLiteralsErrorIfUnexact(
inferrer, receiver.value, receiver.literal, receiver.fileOffset);
if (error != null) {
parent.replaceChild(this, error);
inferredType = const BottomType();
return null;
}
} else if (receiver is ShadowLargeIntLiteral) {
ShadowLargeIntLiteral receiver = this.receiver;
if (!receiver.isParenthesized) {
if (inferrer.isDoubleContext(typeContext)) {
double doubleValue = receiver.asDouble(negated: true);
if (doubleValue != null) {
parent.replaceChild(
this, DoubleLiteral(doubleValue)..fileOffset = fileOffset);
inferredType = inferrer.coreTypes.doubleClass.rawType;
return null;
}
}
int intValue = receiver.asInt64(negated: true);
if (intValue == null) {
Expression error = inferrer.helper.buildProblem(
templateIntegerLiteralIsOutOfRange
.withArguments(receiver.literal),
receiver.fileOffset,
receiver.literal.length);
parent.replaceChild(this, error);
inferredType = const BottomType();
return null;
}
if (intValue != null) {
Expression error = checkWebIntLiteralsErrorIfUnexact(
inferrer, intValue, receiver.literal, receiver.fileOffset);
if (error != null) {
parent.replaceChild(this, error);
inferredType = const BottomType();
return null;
}
this.receiver = IntLiteral(-intValue)
..fileOffset = this.receiver.fileOffset
..parent = this;
}
}
}
}
var inferenceResult = inferrer.inferMethodInvocation(
this, receiver, fileOffset, _isImplicitCall, typeContext,
desugaredInvocation: this);
@ -2670,6 +2847,10 @@ class ShadowTypeInferrer extends TypeInferrerImpl {
}
}
return inferredType;
} else if (expression is IntLiteral) {
return coreTypes.intClass.rawType;
} else if (expression is DoubleLiteral) {
return coreTypes.doubleClass.rawType;
} else {
// Encountered an expression type for which type inference is not yet
// implemented, so just infer dynamic for now.

View file

@ -577,6 +577,22 @@ abstract class TypeInferrerImpl extends TypeInferrer {
/// inference.
TypePromoter get typePromoter;
bool isDoubleContext(DartType typeContext) {
// A context is a double context if double is assignable to it but int is
// not. That is the type context is a double context if it is:
// * double
// * FutureOr<T> where T is a double context
//
// We check directly, rather than using isAssignable because it's simpler.
while (typeContext is InterfaceType &&
typeContext.classNode == coreTypes.futureOrClass &&
typeContext.typeArguments.isNotEmpty) {
InterfaceType type = typeContext;
typeContext = type.typeArguments.first;
}
return typeContext == coreTypes.doubleClass.rawType;
}
bool isAssignable(DartType expectedType, DartType actualType) {
return typeSchemaEnvironment.isSubtypeOf(expectedType, actualType) ||
typeSchemaEnvironment.isSubtypeOf(actualType, expectedType);

View file

@ -2672,7 +2672,7 @@ InterpolationInUri:
analyzerCode: INVALID_LITERAL_IN_CONFIGURATION
IntegerLiteralIsOutOfRange:
template: "The integer literal #lexeme can't be represented in 64 bits."
template: "The integer literal #string can't be represented in 64 bits."
tip: "Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808."
analyzerCode: INTEGER_LITERAL_OUT_OF_RANGE

View file

@ -59,7 +59,6 @@ import 'package:front_end/src/fasta/kernel/kernel_expression_generator.dart'
KernelDelayedAssignment,
KernelDelayedPostfixIncrement,
KernelIndexedAccessGenerator,
KernelIntAccessGenerator,
KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelPrefixUseGenerator,
@ -222,8 +221,6 @@ main() {
"ReadOnlyAccessGenerator(offset: 4, expression: expression,"
" plainNameForRead: foo, value: null)",
new KernelReadOnlyAccessGenerator(helper, token, expression, "foo"));
check("IntAccessGenerator(offset: 4, lexeme: myToken)",
new KernelIntAccessGenerator(helper, token));
check(
"ParenthesizedExpressionGenerator(offset: 4, expression: expression,"
" plainNameForRead: null, value: null)",

View file

@ -32,6 +32,7 @@ instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError #
instantiate_to_bound/typedef_super_bounded_type: Fail # Issue 33444
invocations: Fail
micro: Fail # External method marked abstract.
minimum_int: Crash # Min int literal not supported in non-strong mode.
named_parameters: Fail # Missing types and unnecessary default values.
optional: Fail # Unnecessary default values.
rasta/abstract_constructor: Fail

View file

@ -2,7 +2,7 @@
// 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.
/*@testedFeatures=inference*/
/*@testedFeatures=inference,error*/
library test;
import 'dart:math';
@ -21,23 +21,22 @@ f() {
printDouble(/*@typeArgs=double*/ min(1.0, 2.0));
// No help for user-defined functions from num->num->num.
printInt(/*info:DOWN_CAST_IMPLICIT*/ myMax(1, 2));
printInt(myMax(1, 2));
printInt(myMax(1, 2) as int);
// Mixing int and double means return type is num.
printInt(
/*@typeArgs=int*/ max(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
/*@typeArgs=int*/ max(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
printInt(
/*@typeArgs=int*/ min(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
/*@typeArgs=int*/ min(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
printDouble(
/*@typeArgs=double*/ max(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
/*@typeArgs=double*/ max(1, 2.0));
printDouble(
/*@typeArgs=double*/ min(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
/*@typeArgs=double*/ min(1, 2.0));
// Types other than int and double are not accepted.
printInt(/*@typeArgs=int*/ min(
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ "hi",
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ "there"));
/*@error=ArgumentTypeNotAssignable*/ "hi",
/*@error=ArgumentTypeNotAssignable*/ "there"));
}
main() {}

View file

@ -1,34 +1,24 @@
// Formatted problems:
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:29:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:28:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
// /*@typeArgs=int*/ max(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
// ^
// /*@typeArgs=int*/ max(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
// ^
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:31:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:30:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
// /*@typeArgs=int*/ min(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
// ^
// /*@typeArgs=int*/ min(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
// ^
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:33:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
// /*@typeArgs=double*/ max(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
// ^
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:35:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
// /*@typeArgs=double*/ min(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
// ^
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:38:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
// /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ "hi",
// ^
// /*@error=ArgumentTypeNotAssignable*/ "hi",
// ^
//
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:40:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
// pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
// Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
// /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ "there"));
// ^
// /*@error=ArgumentTypeNotAssignable*/ "there"));
// ^
library test;
import self as self;
@ -48,28 +38,22 @@ static method f() → dynamic {
self::printDouble(math::min<core::double>(1.0, 2.0));
self::printInt(self::myMax(1, 2) as{TypeError} core::int);
self::printInt(self::myMax(1, 2) as core::int);
self::printInt(math::max<core::int>(1, let dynamic _ = null in let final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:29:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
self::printInt(math::max<core::int>(1, let dynamic _ = null in let final dynamic #t1 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:28:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*@typeArgs=int*/ max(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
^" in let final dynamic #t2 = 2.0 in null));
self::printInt(math::min<core::int>(1, let dynamic _ = null in let final dynamic #t3 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:31:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
/*@typeArgs=int*/ max(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
^" in let final dynamic #t2 = 2.0 in null));
self::printInt(math::min<core::int>(1, let dynamic _ = null in let final dynamic #t3 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:30:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*@typeArgs=int*/ min(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
^" in let final dynamic #t4 = 2.0 in null));
self::printDouble(math::max<core::double>(let dynamic _ = null in let final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:33:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
/*@typeArgs=double*/ max(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
^" in let final dynamic #t6 = 1 in null, 2.0));
self::printDouble(math::min<core::double>(let dynamic _ = null in let final dynamic #t7 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:35:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
/*@typeArgs=double*/ min(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
^" in let final dynamic #t8 = 1 in null, 2.0));
self::printInt(math::min<core::int>(let dynamic _ = null in let final dynamic #t9 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
/*@typeArgs=int*/ min(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
^" in let final dynamic #t4 = 2.0 in null));
self::printDouble(math::max<core::double>(1.0, 2.0));
self::printDouble(math::min<core::double>(1.0, 2.0));
self::printInt(math::min<core::int>(let dynamic _ = null in let final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:38:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ \"hi\",
^" in let final dynamic #t10 = "hi" in null, let dynamic _ = null in let final dynamic #t11 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:40:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
/*@error=ArgumentTypeNotAssignable*/ \"hi\",
^" in let final dynamic #t6 = "hi" in null, let dynamic _ = null in let final dynamic #t7 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ \"there\"));
^" in let final dynamic #t12 = "there" in null));
/*@error=ArgumentTypeNotAssignable*/ \"there\"));
^" in let final dynamic #t8 = "there" in null));
}
static method main() → dynamic {}

View file

@ -16,28 +16,22 @@ static method f() → dynamic {
self::printDouble(math::min<core::double>(1.0, 2.0));
self::printInt(self::myMax(1, 2) as{TypeError} core::int);
self::printInt(self::myMax(1, 2) as core::int);
self::printInt(math::max<core::int>(1, let<BottomType> _ = null in let final dynamic #t1 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:29:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
self::printInt(math::max<core::int>(1, let<BottomType> _ = null in let final dynamic #t1 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:28:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*@typeArgs=int*/ max(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
^" in let final core::double #t2 = 2.0 in null));
self::printInt(math::min<core::int>(1, let<BottomType> _ = null in let final dynamic #t3 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:31:71: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
/*@typeArgs=int*/ max(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
^" in let final core::double #t2 = 2.0 in null));
self::printInt(math::min<core::int>(1, let<BottomType> _ = null in let final dynamic #t3 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:30:69: Error: The argument type 'dart.core::double' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*@typeArgs=int*/ min(1, /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 2.0));
^" in let final core::double #t4 = 2.0 in null));
self::printDouble(math::max<core::double>(let<BottomType> _ = null in let final dynamic #t5 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:33:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
/*@typeArgs=double*/ max(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
^" in let final core::int #t6 = 1 in null, 2.0));
self::printDouble(math::min<core::double>(let<BottomType> _ = null in let final dynamic #t7 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:35:71: Error: The argument type 'dart.core::int' can't be assigned to the parameter type 'dart.core::double'.
Try changing the type of the parameter, or casting the argument to 'dart.core::double'.
/*@typeArgs=double*/ min(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 1, 2.0));
^" in let final core::int #t8 = 1 in null, 2.0));
self::printInt(math::min<core::int>(let<BottomType> _ = null in let final dynamic #t9 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
/*@typeArgs=int*/ min(1, /*@error=ArgumentTypeNotAssignable*/ 2.0));
^" in let final core::double #t4 = 2.0 in null));
self::printDouble(math::max<core::double>(1.0, 2.0));
self::printDouble(math::min<core::double>(1.0, 2.0));
self::printInt(math::min<core::int>(let<BottomType> _ = null in let final dynamic #t5 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:38:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ \"hi\",
^" in let final core::String #t10 = "hi" in null, let<BottomType> _ = null in let final dynamic #t11 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:40:46: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
/*@error=ArgumentTypeNotAssignable*/ \"hi\",
^" in let final core::String #t6 = "hi" in null, let<BottomType> _ = null in let final dynamic #t7 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/generic_methods_dart_math_min_max.dart:39:44: Error: The argument type 'dart.core::String' can't be assigned to the parameter type 'dart.core::int'.
Try changing the type of the parameter, or casting the argument to 'dart.core::int'.
/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ \"there\"));
^" in let final core::String #t12 = "there" in null));
/*@error=ArgumentTypeNotAssignable*/ \"there\"));
^" in let final core::String #t8 = "there" in null));
}
static method main() → dynamic {}

View file

@ -381,26 +381,6 @@ LanguageFeatures/Super_Mixins/mixin_member_neg_t01: CompileTimeError
LanguageFeatures/Super_Mixins/mixin_member_neg_t02: CompileTimeError
LanguageFeatures/Super_Mixins/super_invocation_neg_t01/03: MissingCompileTimeError
LanguageFeatures/Super_Mixins/super_invocation_t01: CompileTimeError
LanguageFeatures/int-to-double/arguments_binding_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/arguments_binding_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_class_member_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_class_member_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_global_variable_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_global_variable_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_local_variable_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_local_variable_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_super_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_super_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_this_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/assignment_this_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/max_acceptable_value_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/min_acceptable_values_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/representation_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/representation_t02: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/representation_t03: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/representation_t04: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/return_value_t01: CompileTimeError # Please triage this failure
LanguageFeatures/int-to-double/return_value_t02: CompileTimeError # Please triage this failure
[ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
LibTest/io/Link/renameSync_A02_t01: RuntimeError, Pass

View file

@ -1,3 +1,7 @@
// Copyright (c) 2018, 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.
import 'package:expect/expect.dart';
const String realMaxInt64Value = '9223372036854775807';
@ -7,26 +11,26 @@ const int i21 = 2097152;
main() {
int minInt64Value = -1 * i21 * i21 * i21;
minInt64Value = -9223372036854775807 - 1; /// 01: ok
minInt64Value = -9223372036854775808; /// 02: ok
minInt64Value = -(9223372036854775808); /// 03: compile-time error
minInt64Value = -(0x8000000000000000); /// 04: ok
minInt64Value = 0x8000000000000000; /// 05: ok
minInt64Value = -0x8000000000000000; /// 06: ok
minInt64Value = -9223372036854775807 - 1; //# 01: ok
minInt64Value = -9223372036854775808; //# 02: ok
minInt64Value = -(9223372036854775808); //# 03: compile-time error
minInt64Value = -(0x8000000000000000); //# 04: ok
minInt64Value = 0x8000000000000000; //# 05: ok
minInt64Value = -0x8000000000000000; //# 06: ok
Expect.equals('$minInt64Value', realMinInt64Value);
Expect.equals('${minInt64Value - 1}', realMaxInt64Value);
int maxInt64Value = 1 * i21 * i21 * i21 - 1;
maxInt64Value = 9223372036854775807; /// 11: ok
maxInt64Value = 9223372036854775807; /// 12: ok
maxInt64Value = 9223372036854775808 - 1; /// 13: compile-time error
maxInt64Value = -9223372036854775808 - 1; /// 14: ok
maxInt64Value = -9223372036854775809; /// 15: compile-time error
maxInt64Value = 0x8000000000000000 - 1; /// 16: ok
maxInt64Value = -0x8000000000000000 - 1; /// 17: ok
maxInt64Value = -0x8000000000000001; /// 18: compile-time error
maxInt64Value = -(0x8000000000000001); /// 19: ok
maxInt64Value = 9223372036854775807; //# 11: ok
maxInt64Value = 9223372036854775807; //# 12: ok
maxInt64Value = 9223372036854775808 - 1; //# 13: compile-time error
maxInt64Value = -9223372036854775808 - 1; //# 14: ok
maxInt64Value = -9223372036854775809; //# 15: compile-time error
maxInt64Value = 0x8000000000000000 - 1; //# 16: ok
maxInt64Value = -0x8000000000000000 - 1; //# 17: ok
maxInt64Value = -0x8000000000000001; //# 18: compile-time error
maxInt64Value = -(0x8000000000000001); //# 19: ok
Expect.equals('$maxInt64Value', realMaxInt64Value);
Expect.equals('${maxInt64Value + 1}', realMinInt64Value);

View file

@ -14,14 +14,6 @@ mixin_constructor_forwarding/optional_positional_parameters_test/none: CompileTi
[ $compiler != dart2analyzer ]
switch_case_warn_test: Skip # Analyzer only, see language_analyzer2.status
[ $compiler == dart2js ]
double_literals/*: Skip # https://github.com/dart-lang/sdk/issues/34356
invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34011
void/*: Skip # https://github.com/dart-lang/sdk/issues/34011
[ $compiler == fasta ]
double_literals/*: Skip # https://github.com/dart-lang/sdk/issues/34357
[ $compiler == spec_parser ]
double_literals/*: Skip # https://github.com/dart-lang/sdk/issues/34355
invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34015
@ -222,9 +214,6 @@ type_parameter_test/05: Pass
[ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
*: SkipByDesign # Deprecating all Dart1 modes of execution
[ $compiler == app_jit || $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp || $compiler == none || $compiler == precompiler ]
double_literals/*: Skip # https://github.com/dart-lang/sdk/issues/34358
[ $compiler == app_jit || $compiler == none ]
invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34013
library_env_test/has_no_mirror_support: RuntimeError, OK

View file

@ -255,8 +255,6 @@ constants_test/05: MissingCompileTimeError
covariant_subtyping_test: RuntimeError
deferred_load_library_wrong_args_test/01: CompileTimeError
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in ddk
double_literals/double_literal_coercion_test: CompileTimeError # Issue 34357 - CFE needs to implement this
double_literals/implicit_double_context_test: CompileTimeError # Issue 34357 - CFE needs to implement this
dynamic_prefix_core_test/none: CompileTimeError
emit_const_fields_test: CompileTimeError # Issue 31533
external_test/21: CompileTimeError