From aa6c3d0bde78bdbed6f6ff2ee18cff2942c83d07 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 24 Jul 2017 22:39:29 -0400 Subject: [PATCH] treat String as immutable in `===`. part of #22193 --- src/builtins.c | 13 +++++++++++++ src/codegen.cpp | 3 ++- test/strings/basic.jl | 10 ++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/builtins.c b/src/builtins.c index 3a0014144a107..b4b6cf4fbd43c 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -121,6 +121,12 @@ JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b) jl_datatype_t *dtb = (jl_datatype_t*)b; return dta->name == dtb->name && compare_svec(dta->parameters, dtb->parameters); } + if (dt == jl_string_type) { + size_t l = jl_string_len(a); + if (jl_string_len(b) != l) + return 0; + return !memcmp(jl_string_data(a), jl_string_data(b), l); + } if (dt->mutabl) return 0; size_t sz = jl_datatype_size(dt); if (sz == 0) return 1; @@ -186,6 +192,13 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) #else if (v == jl_ANY_flag) return 0x8ee30bdd; #endif + if (dt == jl_string_type) { +#ifdef _P64 + return memhash_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); +#else + return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); +#endif + } if (dt->mutabl) return inthash((uintptr_t)v); size_t sz = jl_datatype_size(tv); uintptr_t h = jl_object_id(tv); diff --git a/src/codegen.cpp b/src/codegen.cpp index e36e6b2c0fdd0..ac0c1e664c5f4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2349,7 +2349,8 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva if ((jl_is_type_type(rt1) && jl_is_leaf_type(jl_tparam0(rt1))) || (jl_is_type_type(rt2) && jl_is_leaf_type(jl_tparam0(rt2)))) // can compare leaf types by pointer ptr_comparable = 1; - if (rt1 == (jl_value_t*)jl_simplevector_type && rt2 == (jl_value_t*)jl_simplevector_type) + if ((rt1 == (jl_value_t*)jl_string_type && rt2 == (jl_value_t*)jl_string_type) || + (rt1 == (jl_value_t*)jl_simplevector_type && rt2 == (jl_value_t*)jl_simplevector_type)) ptr_comparable = 0; // technically mutable, but compared by contents if (ptr_comparable) { Value *varg1 = arg1.constant ? literal_pointer_val(ctx, arg1.constant) : arg1.V; diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 2f2dff88546a1..a65a57af8fe14 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -8,6 +8,16 @@ @test eltype(GenericString) == Char @test start("abc") == 1 @test cmp("ab","abc") == -1 +@test "abc" === "abc" +@test "ab" !== "abc" +@test string("ab", 'c') === "abc" +codegen_egal_of_strings(x, y) = (x===y, x!==y) +@test codegen_egal_of_strings(string("ab", 'c'), "abc") === (true, false) +let strs = ["", "a", "a b c", "до свидания"] + for x in strs, y in strs + @test (x === y) == (object_id(x) == object_id(y)) + end +end # {starts,ends}with @test startswith("abcd", 'a')