From 18c76007b1e00a2afa1e9990cd54385b059c83bb Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Mon, 3 Mar 2014 09:52:51 +0000 Subject: [PATCH] Check that const-map keys don't override equals. BUG= http://dartbug.com/17123 R=karlklose@google.com Review URL: https://codereview.chromium.org//179293005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@33201 260f80e4-7a28-3924-810f-c04153c831b5 --- .../implementation/resolution/members.dart | 21 ++++++++++++++ .../compiler/implementation/warnings.dart | 5 ++-- tests/co19/co19-dart2js.status | 2 +- tests/language/const_map2_test.dart | 29 +++++++++++++++++++ tests/language/language.status | 3 ++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/language/const_map2_test.dart diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart index 69e3b45b9d0..1ea01a85e38 100644 --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart @@ -3098,11 +3098,32 @@ class ResolverVisitor extends MappingVisitor { return null; } + void checkConstMapKeysDontOverrideEquals(Spannable spannable, + MapConstant map) { + for (Constant key in map.keys.entries) { + if (!key.isObject()) continue; + ObjectConstant objectConstant = key; + DartType keyType = objectConstant.type; + ClassElement cls = keyType.element; + if (cls == compiler.stringClass) continue; + Element equals = cls.lookupMember('=='); + if (equals.getEnclosingClass() != compiler.objectClass) { + compiler.reportError(spannable, + MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, + {'type': keyType}); + } + } + } + void analyzeConstant(Node node, {bool isConst: true}) { addDeferredAction(enclosingElement, () { Constant constant = compiler.constantHandler.compileNodeWithDefinitions( node, mapping, isConst: isConst); + if (isConst && constant != null && constant.isMap()) { + checkConstMapKeysDontOverrideEquals(node, constant); + } + // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names // a class that will be instantiated outside the program by attaching a // native class dispatch record referencing the interceptor. diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart index 8cef76fbfc3..0b33526621d 100644 --- a/sdk/lib/_internal/compiler/implementation/warnings.dart +++ b/sdk/lib/_internal/compiler/implementation/warnings.dart @@ -556,8 +556,9 @@ main() => new C(); static const MessageKind CONSTRUCTOR_IS_NOT_CONST = const MessageKind( "Constructor is not a 'const' constructor."); - static const MessageKind KEY_NOT_A_STRING_LITERAL = const MessageKind( - "Map-literal key not a string literal."); + static const MessageKind CONST_MAP_KEY_OVERRIDES_EQUALS = + const MessageKind( + "Const-map key type '#{type}' overrides 'operator =='."); static const MessageKind NO_SUCH_LIBRARY_MEMBER = const MessageKind( "'#{libraryName}' has no member named '#{memberName}'."); diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status index b7c55d5c449..b3e95c6ba6e 100644 --- a/tests/co19/co19-dart2js.status +++ b/tests/co19/co19-dart2js.status @@ -260,6 +260,7 @@ LibTest/math/cos_A01_t01: Fail # co19 issue 44 [ $compiler == dart2js ] Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: RuntimeError # compiler cancelled: cannot resolve type T Language/07_Classes/3_Setters_A04_t03: RuntimeError # http://dartbug.com/5023 +Language/12_Expressions/07_Maps_A11_t01: CompileTimeError # Maybe ok. Issue 17207 [ $compiler == dart2js && $jscl ] LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # IllegalJSRegExpException: '\c(' 'SyntaxError: Invalid regular expression: /\c(/: Unterminated group' @@ -638,7 +639,6 @@ Language/07_Classes/6_Constructors/2_Factories_A10_t02: fail # co19-roll r587: P Language/07_Classes/6_Constructors/2_Factories_A10_t03: fail # co19-roll r587: Please triage this failure Language/10_Generics/09_Generics_A01_t17: fail # co19-roll r587: Please triage this failure Language/12_Expressions/06_Symbols_A01_t02: CompileTimeError # co19-roll r623: Please triage this failure -Language/12_Expressions/07_Maps_A13_t01: MissingCompileTimeError # co19-roll r607: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A06_t15: CompileTimeError # co19-roll r651: Please triage this failure Language/12_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t17: MissingCompileTimeError # co19-roll r651: Please triage this failure Language/12_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t18: MissingCompileTimeError # co19-roll r651: Please triage this failure diff --git a/tests/language/const_map2_test.dart b/tests/language/const_map2_test.dart new file mode 100644 index 00000000000..6b599f70d15 --- /dev/null +++ b/tests/language/const_map2_test.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2014, 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"; + +class A { + const factory A() = B; +} + +class B implements A { + const B(); + + operator ==(o) => true; /// 00: compile-time error +} + +confuse(x) { + if (new DateTime.now() == 42) return confuse(2); + return x; +} + +main() { + // It is a compile-time error if the key type overrides operator ==. + var m = const { const A(): 42 }; + Expect.equals(42, m[confuse(const B())]); + + m = const { "foo": 99, const A(): 499 }; + Expect.equals(499, m[confuse(const B())]); +} diff --git a/tests/language/language.status b/tests/language/language.status index ca70884e8bc..16f9b9a84e7 100644 --- a/tests/language/language.status +++ b/tests/language/language.status @@ -27,6 +27,9 @@ deferred_duplicate_prefix1_test/01: Fail deferred_duplicate_prefix2_test/01: Fail deferred_duplicate_prefix3_test/01: Fail +[ $compiler == dartanalyzer ] +const_map2_test/00: MissingCompileTimeError # Issue 17209 + [ $compiler == none && $runtime == vm ] class_keyword_test/02: MissingCompileTimeError # Issue 13627 override_inheritance_mixed_test/08: MissingCompileTimeError # Issue 16137