mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:01:42 +00:00
Issue 47364. Add context messages to TYPE_ARGUMENT_NOT_MATCHING_BOUNDS.
We include two pieces of data: 1. If the named type was raw, the instantated type. 2. If the type was not regular bounded, also the inverted type. Bug: https://github.com/dart-lang/sdk/issues/47364 Change-Id: Idc8fce998f755e68bee0ada2caa715b59101cc84 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215484 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
6e987219c4
commit
2b36a3945d
|
@ -8,12 +8,14 @@ import 'package:analyzer/dart/analysis/features.dart';
|
|||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/diagnostic/diagnostic.dart';
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/error/listener.dart';
|
||||
import 'package:analyzer/src/dart/ast/extensions.dart';
|
||||
import 'package:analyzer/src/dart/element/type_algebra.dart';
|
||||
import 'package:analyzer/src/dart/element/type_schema.dart';
|
||||
import 'package:analyzer/src/dart/element/type_system.dart';
|
||||
import 'package:analyzer/src/diagnostic/diagnostic.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
||||
import 'package:analyzer/src/generated/resolver.dart';
|
||||
|
@ -265,18 +267,21 @@ class TypeArgumentsVerifier {
|
|||
/// Verify that the type arguments in the given [namedType] are all within
|
||||
/// their bounds.
|
||||
void _checkForTypeArgumentNotMatchingBounds(NamedType namedType) {
|
||||
var type = namedType.type;
|
||||
final type = namedType.type;
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<TypeParameterElement> typeParameters;
|
||||
List<DartType> typeArguments;
|
||||
var alias = type.alias;
|
||||
final List<TypeParameterElement> typeParameters;
|
||||
final String elementName;
|
||||
final List<DartType> typeArguments;
|
||||
final alias = type.alias;
|
||||
if (alias != null) {
|
||||
elementName = alias.element.name;
|
||||
typeParameters = alias.element.typeParameters;
|
||||
typeArguments = alias.typeArguments;
|
||||
} else if (type is InterfaceType) {
|
||||
elementName = type.element.name;
|
||||
typeParameters = type.element.typeParameters;
|
||||
typeArguments = type.typeArguments;
|
||||
} else {
|
||||
|
@ -289,7 +294,7 @@ class TypeArgumentsVerifier {
|
|||
|
||||
// Check for regular-bounded.
|
||||
List<_TypeArgumentIssue>? issues;
|
||||
var substitution = Substitution.fromPairs(typeParameters, typeArguments);
|
||||
final substitution = Substitution.fromPairs(typeParameters, typeArguments);
|
||||
for (var i = 0; i < typeArguments.length; i++) {
|
||||
var typeParameter = typeParameters[i];
|
||||
var typeArgument = typeArguments[i];
|
||||
|
@ -325,6 +330,49 @@ class TypeArgumentsVerifier {
|
|||
return;
|
||||
}
|
||||
|
||||
List<DiagnosticMessage>? buildContextMessages({
|
||||
List<DartType>? invertedTypeArguments,
|
||||
}) {
|
||||
final messages = <DiagnosticMessage>[];
|
||||
|
||||
void addMessage(String message) {
|
||||
messages.add(
|
||||
DiagnosticMessageImpl(
|
||||
filePath: _errorReporter.source.fullName,
|
||||
length: namedType.length,
|
||||
message: message,
|
||||
offset: namedType.offset,
|
||||
url: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String typeArgumentsToString(List<DartType> typeArguments) {
|
||||
return typeArguments
|
||||
.map((e) => e.getDisplayString(withNullability: true))
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
if (namedType.typeArguments == null) {
|
||||
var typeStr = '$elementName<${typeArgumentsToString(typeArguments)}>';
|
||||
addMessage(
|
||||
"The raw type was instantiated as '$typeStr', "
|
||||
"and is not regular-bounded.",
|
||||
);
|
||||
}
|
||||
|
||||
if (invertedTypeArguments != null) {
|
||||
var invertedTypeStr =
|
||||
'$elementName<${typeArgumentsToString(invertedTypeArguments)}>';
|
||||
addMessage(
|
||||
"The inverted type '$invertedTypeStr' is also not regular-bounded, "
|
||||
"so the type is not well-bounded.",
|
||||
);
|
||||
}
|
||||
|
||||
return messages.isNotEmpty ? messages : null;
|
||||
}
|
||||
|
||||
// If not allowed to be super-bounded, report issues.
|
||||
if (!_shouldAllowSuperBoundedTypes(namedType)) {
|
||||
for (var issue in issues) {
|
||||
|
@ -332,27 +380,32 @@ class TypeArgumentsVerifier {
|
|||
CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
||||
_typeArgumentErrorNode(namedType, issue.index),
|
||||
[issue.argument, issue.parameter.name, issue.parameterBound],
|
||||
buildContextMessages(),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare type arguments for checking for super-bounded.
|
||||
type = _typeSystem.replaceTopAndBottom(type);
|
||||
alias = type.alias;
|
||||
if (alias != null) {
|
||||
typeArguments = alias.typeArguments;
|
||||
} else if (type is InterfaceType) {
|
||||
typeArguments = type.typeArguments;
|
||||
final invertedType = _typeSystem.replaceTopAndBottom(type);
|
||||
final List<DartType> invertedTypeArguments;
|
||||
final invertedAlias = invertedType.alias;
|
||||
if (invertedAlias != null) {
|
||||
invertedTypeArguments = invertedAlias.typeArguments;
|
||||
} else if (invertedType is InterfaceType) {
|
||||
invertedTypeArguments = invertedType.typeArguments;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for super-bounded.
|
||||
substitution = Substitution.fromPairs(typeParameters, typeArguments);
|
||||
for (var i = 0; i < typeArguments.length; i++) {
|
||||
final invertedSubstitution = Substitution.fromPairs(
|
||||
typeParameters,
|
||||
invertedTypeArguments,
|
||||
);
|
||||
for (var i = 0; i < invertedTypeArguments.length; i++) {
|
||||
var typeParameter = typeParameters[i];
|
||||
var typeArgument = typeArguments[i];
|
||||
var typeArgument = invertedTypeArguments[i];
|
||||
|
||||
var bound = typeParameter.bound;
|
||||
if (bound == null) {
|
||||
|
@ -360,13 +413,16 @@ class TypeArgumentsVerifier {
|
|||
}
|
||||
|
||||
bound = _libraryElement.toLegacyTypeIfOptOut(bound);
|
||||
bound = substitution.substituteType(bound);
|
||||
bound = invertedSubstitution.substituteType(bound);
|
||||
|
||||
if (!_typeSystem.isSubtypeOf(typeArgument, bound)) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
||||
_typeArgumentErrorNode(namedType, i),
|
||||
[typeArgument, typeParameter.name, bound],
|
||||
buildContextMessages(
|
||||
invertedTypeArguments: invertedTypeArguments,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3508,8 +3508,10 @@ void test() {
|
|||
class C<T0 extends List<T1>, T1 extends List<T0>> {}
|
||||
class D extends C {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 69, 1)]),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 69, 1)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -3523,8 +3525,9 @@ void test() {
|
|||
}
|
||||
''', [
|
||||
error(HintCode.UNUSED_LOCAL_VARIABLE, 73, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 81, 1),
|
||||
error(CompileTimeErrorCode.COULD_NOT_INFER, 81, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 81, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 81, 1)]),
|
||||
]);
|
||||
_assertLocalVarType('c', 'C<List<dynamic>, List<List<dynamic>>>');
|
||||
}
|
||||
|
@ -3560,7 +3563,11 @@ typedef T F<T>(T x);
|
|||
class C<T extends F<T>> {}
|
||||
C c;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1,
|
||||
contextMessages: [
|
||||
message('/home/test/lib/test.dart', 48, 1),
|
||||
message('/home/test/lib/test.dart', 48, 1)
|
||||
]),
|
||||
]);
|
||||
_assertTopVarType('c', 'C<dynamic Function(dynamic)>');
|
||||
}
|
||||
|
|
|
@ -562,7 +562,8 @@ A<String> Function() bar() {
|
|||
return A.foo;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 41, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 41, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 39, 9)]),
|
||||
]);
|
||||
|
||||
var classElement = findElement.class_('A');
|
||||
|
|
|
@ -75,7 +75,8 @@ var t = C<int, int>;
|
|||
class C<T extends num> {}
|
||||
var t = C<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 34, 9)]),
|
||||
]);
|
||||
|
||||
var typeLiteral = findNode.typeLiteral('C<String>;');
|
||||
|
@ -142,7 +143,8 @@ class C<T> {}
|
|||
typedef CA<T extends num> = C<T>;
|
||||
var t = CA<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 59, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 59, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 56, 10)]),
|
||||
]);
|
||||
|
||||
var typeLiteral = findNode.typeLiteral('CA<String>;');
|
||||
|
@ -374,7 +376,8 @@ var t = Fn<int, String>;
|
|||
typedef Fn<T extends num> = void Function(T);
|
||||
var t = Fn<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 57, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 57, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 54, 10)]),
|
||||
]);
|
||||
|
||||
var typeLiteral = findNode.typeLiteral('Fn<String>;');
|
||||
|
|
|
@ -33,10 +33,12 @@ main() {
|
|||
P._();
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 154, 1)]),
|
||||
error(CompileTimeErrorCode.COULD_NOT_INFER, 154, 3),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 154, 1)]),
|
||||
error(CompileTimeErrorCode.COULD_NOT_INFER, 154, 3),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -58,8 +60,9 @@ main() {
|
|||
}
|
||||
''', [
|
||||
error(HintCode.UNUSED_LOCAL_VARIABLE, 120, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 124, 1),
|
||||
error(CompileTimeErrorCode.COULD_NOT_INFER, 124, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 124, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 124, 1)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ class C {
|
|||
C(G<B> this.f) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 71, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 71, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 69, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -140,7 +141,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
G<B> f() => throw 0;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 46, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -151,7 +153,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
typedef G<B> f();
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 54, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -162,7 +165,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
f(G<B> h()) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 48, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -184,7 +188,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
var b = 1 is G<B>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 61, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 61, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 59, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -252,7 +257,8 @@ class C {
|
|||
G<B> m() => throw 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 60, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 60, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 58, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -297,7 +303,8 @@ class Bar<T extends Foo<T>> {}
|
|||
class Baz extends Bar {}
|
||||
void main() {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 65, 3)]),
|
||||
]);
|
||||
// Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
|
||||
assertType(result.unit.declaredElement!.getType('Baz')!.supertype,
|
||||
|
@ -311,7 +318,8 @@ class B {}
|
|||
typedef F<T extends A>();
|
||||
F<B> fff = (throw 42);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 48, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -350,7 +358,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
f(G<B> g) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 48, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -376,7 +385,8 @@ class C<E> {}
|
|||
class D<E extends A> {}
|
||||
C<D<B>> c = (throw 0);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 64, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 64, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 62, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -388,7 +398,8 @@ class C {}
|
|||
class G<E extends A> {}
|
||||
class D<F extends G<B>> {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 77, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 77, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 75, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -399,7 +410,8 @@ class B {}
|
|||
class G<E extends A> {}
|
||||
G<B> g = (throw 0);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 46, 4)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -487,7 +499,8 @@ typedef FB<T extends F> = S Function<S extends T>(S);
|
|||
class CB<T extends F> {}
|
||||
void f(CB<FB<F>> a) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 119, 5),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 119, 5,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 116, 9)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -613,7 +626,8 @@ typedef X<T> = A;
|
|||
class A<T extends A<T>> {}
|
||||
typedef X<T> = A;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 42, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 42, 1,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -623,7 +637,8 @@ class A {}
|
|||
typedef X<T extends A> = Map<int, T>;
|
||||
void f(X<String> a) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 58, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 58, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 56, 9)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -642,7 +657,11 @@ typedef A<X> = X Function(X);
|
|||
typedef G<X extends A<X>> = void Function<Y extends X>();
|
||||
foo(G g) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 92, 1),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 92, 1,
|
||||
contextMessages: [
|
||||
message('/home/test/lib/test.dart', 92, 1),
|
||||
message('/home/test/lib/test.dart', 92, 1)
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -698,7 +717,8 @@ A get foo => throw 0;
|
|||
class C<T extends int> {}
|
||||
var t = C<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 34, 9)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -707,7 +727,8 @@ var t = C<String>;
|
|||
typedef Cb<T extends int> = void Function();
|
||||
var t = Cb<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 53, 10)]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -717,7 +738,8 @@ class C {}
|
|||
typedef D<T extends int> = C;
|
||||
var t = D<String>;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6),
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6,
|
||||
contextMessages: [message('/home/test/lib/test.dart', 49, 9)]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue