diff --git a/spec/std/slice_spec.cr b/spec/std/slice_spec.cr index 505db8f09109..29b475009578 100644 --- a/spec/std/slice_spec.cr +++ b/spec/std/slice_spec.cr @@ -489,6 +489,20 @@ describe "Slice" do end end + it "#same?" do + slice = Slice[1, 2, 3] + + slice.should be slice + slice.should_not be slice.dup + slice.should_not be Slice[1, 2, 3] + + (slice + 1).should be slice + 1 + slice.should_not be slice + 1 + + (slice[0, 2]).should be slice[0, 2] + slice.should_not be slice[0, 2] + end + it "does macro []" do slice = Slice[1, 'a', "foo"] slice.should be_a(Slice(Int32 | Char | String)) diff --git a/src/slice.cr b/src/slice.cr index 196a29a768dd..469dd2d65807 100644 --- a/src/slice.cr +++ b/src/slice.cr @@ -845,6 +845,21 @@ struct Slice(T) {% end %} end + # Returns `true` if `self` and *other* point to the same memory, i.e. pointer + # and size are identical. + # + # ``` + # slice = Slice[1, 2, 3] + # slice.same?(slice) # => true + # slice == Slice[1, 2, 3] # => false + # slice.same?(slice + 1) # => false + # (slice + 1).same?(slice + 1) # => true + # slice.same?(slice[0, 2]) # => false + # ``` + def same?(other : self) : Bool + to_unsafe == other.to_unsafe && size == other.size + end + def to_slice : self self end diff --git a/src/spec/expectations.cr b/src/spec/expectations.cr index ac93de54975e..193f86d0de21 100644 --- a/src/spec/expectations.cr +++ b/src/spec/expectations.cr @@ -65,11 +65,19 @@ module Spec end def failure_message(actual_value) - "Expected: #{@expected_value.pretty_inspect} (object_id: #{@expected_value.object_id})\n got: #{actual_value.pretty_inspect} (object_id: #{actual_value.object_id})" + "Expected: #{@expected_value.pretty_inspect} (#{identify(@expected_value)})\n got: #{actual_value.pretty_inspect} (#{identify(actual_value)})" end def negative_failure_message(actual_value) - "Expected: value.same? #{@expected_value.pretty_inspect} (object_id: #{@expected_value.object_id})\n got: #{actual_value.pretty_inspect} (object_id: #{actual_value.object_id})" + "Expected: #{@expected_value.pretty_inspect} (#{identify(@expected_value)})\n got: #{actual_value.pretty_inspect} (#{identify(actual_value)})" + end + + private def identify(value) + if value.responds_to?(:object_id) + "object_id: #{value.object_id}" + else + value.to_unsafe + end end end