mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:09:48 +00:00
[analyzer] Fix #32913, no error for inferring a non-const type argument in a generic function used in a const location
Bug: 32913 Change-Id: I7e5ef10fdd9befdc7d8a19b2c5c5b91639c82666 Fixed: 33439 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/91105 Commit-Queue: Mike Fairhurst <mfairhurst@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
parent
a62b9c8d23
commit
a98f4acd1a
|
@ -24,6 +24,7 @@ import 'package:analyzer/src/dart/constant/utilities.dart';
|
|||
import 'package:analyzer/src/dart/constant/value.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/dart/element/type_visitor.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/generated/constant.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
|
@ -1690,6 +1691,13 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
|
|||
element = element?.declaration;
|
||||
Element variableElement =
|
||||
element is PropertyAccessorElement ? element.variable : element;
|
||||
|
||||
if (node is SimpleIdentifier &&
|
||||
(node.tearOffTypeArgumentTypes?.any(_hasAppliedTypeParameters) ??
|
||||
false)) {
|
||||
_error(node, null);
|
||||
}
|
||||
|
||||
if (variableElement is VariableElementImpl) {
|
||||
// We access values of constant variables here in two cases: when we
|
||||
// compute values of other constant variables, or when we compute values
|
||||
|
@ -1755,6 +1763,13 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Check if any type parameters are referenced by [type], which is an error.
|
||||
bool _hasAppliedTypeParameters(DartType type) {
|
||||
final visitor = _ReferencesTypeParameterVisitor();
|
||||
DartTypeVisitor.visit(type, visitor);
|
||||
return visitor.result;
|
||||
}
|
||||
|
||||
/// Return `true` if the given [targetResult] represents a string and the
|
||||
/// [identifier] is "length".
|
||||
bool _isStringLength(
|
||||
|
@ -1801,6 +1816,27 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A visitor to find if a type contains any [TypeParameterType]s.
|
||||
///
|
||||
/// To find the result, check [result] on this instance after visiting the tree.
|
||||
/// The actual value returned by the visit methods is merely used so that
|
||||
/// [RecursiveTypeVisitor] stops visiting the type once the first type parameter
|
||||
/// type is found.
|
||||
class _ReferencesTypeParameterVisitor extends RecursiveTypeVisitor {
|
||||
/// The result of whether any type parameters were found.
|
||||
bool result = false;
|
||||
|
||||
@override
|
||||
bool visitTypeParameterType(_) {
|
||||
result = true;
|
||||
// Stop visiting at this point.
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool defaultDartType(_) => true; // Continue visiting in this case.
|
||||
}
|
||||
|
||||
/// A utility class that contains methods for manipulating instances of a Dart
|
||||
/// class and for collecting errors during evaluation.
|
||||
class DartObjectComputer {
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2020, 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:analyzer/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../../generated/test_support.dart';
|
||||
import '../dart/resolution/driver_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(NonConstantDefaultValueTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class NonConstantDefaultValueTest extends DriverResolutionTest {
|
||||
test_appliedTypeParameter_defaultConstructorValue() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
class C<T> {
|
||||
final void Function(T) p;
|
||||
const C({this.p = f});
|
||||
}
|
||||
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 83, 1)]);
|
||||
}
|
||||
|
||||
test_appliedTypeParameter_defaultFunctionValue() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
void bar<T>([void Function(T) p = f]) {}
|
||||
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 56, 1)]);
|
||||
}
|
||||
|
||||
test_appliedTypeParameter_defaultMethodValue() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
class C<T> {
|
||||
void foo([void Function(T) p = f]) {}
|
||||
}
|
||||
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 68, 1)]);
|
||||
}
|
||||
|
||||
test_appliedTypeParameter_nested() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
void bar<T>([void Function(List<T>) p = f]) {}
|
||||
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 62, 1)]);
|
||||
}
|
||||
|
||||
test_appliedTypeParameter_nestedFunction() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
void bar<T>([void Function(T Function()) p = f]) {}
|
||||
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 67, 1)]);
|
||||
}
|
||||
|
||||
test_noAppliedTypeParameters_defaultConstructorValue_dynamic() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
class C<T> {
|
||||
final dynamic p;
|
||||
const C({this.p = f});
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_noAppliedTypeParameters_defaultConstructorValue_genericFn() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
class C<T> {
|
||||
final void Function<T>(T) p;
|
||||
const C({this.p = f});
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_noAppliedTypeParameters_defaultFunctionValue_genericFn() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
void bar<T>([void Function<T>(T) p = f]) {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_noAppliedTypeParameters_defaultMethodValue_genericFn() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f<T>(T t) => t;
|
||||
|
||||
class C<T> {
|
||||
void foo([void Function<T>(T) p = f]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
|
@ -288,6 +288,7 @@ import 'non_bool_operand_test.dart' as non_bool_operand;
|
|||
import 'non_constant_case_expression_from_deferred_library_test.dart'
|
||||
as non_constant_case_expression_from_deferred_library;
|
||||
import 'non_constant_case_expression_test.dart' as non_constant_case_expression;
|
||||
import 'non_constant_default_value_test.dart' as non_constant_default_value;
|
||||
import 'non_constant_list_element_from_deferred_library_test.dart'
|
||||
as non_constant_list_element_from_deferred_library;
|
||||
import 'non_constant_list_element_test.dart' as non_constant_list_element;
|
||||
|
@ -808,6 +809,7 @@ main() {
|
|||
undefined_prefixed_name.main();
|
||||
undefined_setter.main();
|
||||
undefined_shown_name.main();
|
||||
non_constant_default_value.main();
|
||||
unnecessary_cast.main();
|
||||
unnecessary_no_such_method.main();
|
||||
unnecessary_non_null_assertion.main();
|
||||
|
|
Loading…
Reference in a new issue