Check mixin of black-listed types.
BUG=http://dartbug.com/12445
R=karlklose@google.com
Review URL: https://codereview.chromium.org//25844002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@28197 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 7a27b1d..af4208d 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -3606,7 +3606,8 @@
DartType supertype = resolveSupertype(element, superMixin.superclass);
Link<Node> link = superMixin.mixins.nodes;
while (!link.isEmpty) {
- supertype = applyMixin(supertype, resolveType(link.head), node);
+ supertype = applyMixin(
+ supertype, checkMixinType(link.head), link.head);
link = link.tail;
}
element.supertype = supertype;
@@ -3657,6 +3658,17 @@
return element.computeType(compiler);
}
+ /// Resolves the mixed type for [mixinNode] and checks that the the mixin type
+ /// is not black-listed. The mixin type is returned.
+ DartType checkMixinType(TypeAnnotation mixinNode) {
+ DartType mixinType = resolveType(mixinNode);
+ if (isBlackListed(mixinType)) {
+ compiler.reportError(mixinNode,
+ MessageKind.CANNOT_MIXIN, {'type': mixinType});
+ }
+ return mixinType;
+ }
+
DartType visitNamedMixinApplication(NamedMixinApplication node) {
compiler.ensure(element != null);
compiler.ensure(element.resolutionState == STATE_STARTED);
@@ -3670,10 +3682,10 @@
DartType supertype = resolveSupertype(element, node.superclass);
Link<Node> link = node.mixins.nodes;
while (!link.tail.isEmpty) {
- supertype = applyMixin(supertype, resolveType(link.head), link.head);
+ supertype = applyMixin(supertype, checkMixinType(link.head), link.head);
link = link.tail;
}
- doApplyMixinTo(element, supertype, resolveType(link.head));
+ doApplyMixinTo(element, supertype, checkMixinType(link.head));
return element.computeType(compiler);
}
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 7d5dcbf..3c3729e 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -668,6 +668,19 @@
static const MessageKind CANNOT_IMPLEMENT = const MessageKind(
"Error: '#{type}' cannot be implemented.");
+ static const MessageKind CANNOT_MIXIN = const MessageKind(
+ "Error: The type '#{type}' can't be mixed in.",
+ howToFix: "Try removing '#{type}' from the 'with' clause.",
+ examples: const ["""
+class C extends Object with String {}
+
+main() => new C();
+""", """
+typedef C = Object with String;
+
+main() => new C();
+"""]);
+
static const MessageKind DUPLICATE_EXTENDS_IMPLEMENTS = const MessageKind(
"Error: '#{type}' can not be both extended and implemented.");
diff --git a/tests/language/mixin_black_listed_test.dart b/tests/language/mixin_black_listed_test.dart
new file mode 100644
index 0000000..809274b
--- /dev/null
+++ b/tests/language/mixin_black_listed_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, 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.
+
+// Check mixin of black-listed types.
+
+import 'package:expect/expect.dart';
+
+class C {}
+class D {}
+
+class C1 extends Object
+with String /// 01: compile-time error
+{}
+
+class D1 extends Object with C
+, Null /// 02: compile-time error
+{}
+
+class E1 extends Object with
+int, /// 03: compile-time error
+C {}
+
+class F1 extends Object with C
+, double /// 04: compile-time error
+, D {}
+
+typedef C2 = Object with num; /// 05: compile-time error
+
+typedef D2 = Object with C
+, bool /// 06: compile-time error
+;
+
+typedef E2 = Object with
+String, /// 07: compile-time error
+C;
+
+typedef F2 = Object with C,
+dynamic, /// 08: compile-time error
+D;
+
+
+main() {
+ Expect.isNotNull(new C1());
+ Expect.isNotNull(new D1());
+ Expect.isNotNull(new E1());
+ Expect.isNotNull(new F1());
+ Expect.isNotNull(new C2()); /// 05: continued
+ Expect.isNotNull(new D2());
+ Expect.isNotNull(new E2());
+ Expect.isNotNull(new F2());
+}