Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

string equality should be based on contents not identity #123

Closed
jyasskin opened this issue Jul 24, 2010 · 4 comments
Closed

string equality should be based on contents not identity #123

jyasskin opened this issue Jul 24, 2010 · 4 comments

Comments

@jyasskin
Copy link
Contributor

$ cat test.rs
fn main() {
  if("0" == "0") {
    log "equal";
  } else {
    log "not equal";
  }
}
$ ./rustboot -L . test.rs -o test.exe && ./test.exe
rt: 0xa0563720:0xbfffece4:0x00100200:     upcall log_str("not equal")

We can work around this in the library, but I'd rather not.

@graydon
Copy link
Contributor

graydon commented Jul 25, 2010

Flat vs. deep equality is something we've talked a bit about during the spring; I believe we settled on the notion that the operators would behave "machine-like" (such that == and < would do shallow, memcmp-like, pointer-comparing versions) and we'd add operators or library code to do deep compares.

Several related rationales here:

  • That the other operators (+, -, !, etc.) are machine-like,
    constant-time, atomic.
  • That deep structural comparison is really only "easy" to define in
    immutable (acyclic) cases, and having "==" only work on immutable
    values would "feel weird" to users.
  • That compare-by-ref is more like what existing languages with
    explicit pointers do for such operators, on the pointer edges.
  • That users will more-likely want to customize the deep version
    than the shallow version, so most APIs will support "pass a
    comparator function" anyway.
  • That the default should be the fastest version.

I'm not sure all these are equally convincing, or at all so. It's a complex topic. Thoughts?

@jyasskin
Copy link
Contributor Author

Above all, I want == to fail to compile in cases where it's going to be confusing. In Java, where == works on String, but you always want to use .equals instead, I tend to write bugs.

I think part of this is my confusion between logically boxed and unboxed types. I was looking at a str as a logically unboxed type, even if there's a pointer involved in its implementation. Similarly, objs, recs, tups, and vecs feel unboxed since I didn't write an @.

I don't think you can get equality right for all types without user (library author) input. You can for strs, and tups, recs, and vecs of primitive types, but any obj could have multiple representations of the same value. I'd leave it a compile error on objs if you don't want to let users overload it.

If == must be defined everywhere (for use in generic functions?), I'd expect it to compare boxed values as pointers, and unboxed values recursively down to primitive types or boxes. That ensures that it never falls into a cycle, without a mutability restriction. Unfortunately, that still conflicts with my first rule on user-defined types like hashtables, where it'll give the wrong answer.

I don't really buy that Rust should trade safety (expected results from ==) for speed (pointer comparisons).

@graydon
Copy link
Contributor

graydon commented Jan 27, 2011

Shifted to rustc.

@graydon
Copy link
Contributor

graydon commented May 5, 2011

This is done in rustc some time before abd78f2.

@graydon graydon closed this as completed May 5, 2011
arielb1 pushed a commit to arielb1/rust that referenced this issue Apr 10, 2015
In particular:

* The RFC associated with rust-lang#127 should have had a link to rust-lang#19 as well
  (and has been assigned RFC rust-lang#19); it also was revised to match the
  markdown href style of other RFCs.

* RFC rust-lang#34 needed its header entries filled in,

* RFC rust-lang#123 had a typo in its header, and

* RC rust-lang#155 was revised to match the markdown href style of other RFCs.
kazcw pushed a commit to kazcw/rust that referenced this issue Oct 23, 2018
* avx: _mm256_movedup_pd

* avx: _mm256_lddqu_si256

* avx: _mm256_rcp_ps

* avx: _mm256_rsqrt_ps

* avx: _mm256_unpackhi_pd

* avx: _mm256_unpackhi_ps

* avx: _mm256_unpacklo_pd, _mm256_unpacklo_ps

* avx: _mm256_testz_si256

* avx: _mm256_testc_si256

* avx: _mm256_testz_pd

* avx: _mm256_testc_pd

* avx: _mm256_testnzc_pd

* avx: _mm_testz_pd

* avx: _mm_testc_pd

* avx: _mm_testnzc_pd

* avx: _mm256_testz_ps, _mm256_testc_ps, _mm256_testnzc_ps

* avx: _mm_testz_ps, _mm_testc_ps, _mm_testnzc_ps

* avx: _mm256_movemask_pd, _mm256_movemask_ps

* avx: _mm256_setzero_pd, _mm256_setzero_ps

* avx: _mm256_setzero_si256

* avx: _mm256_set_pd, _mm256_set_ps

* avx: _mm256_set_epi8

* avx: _mm256_set_epi16

* avx: _mm256_set_epi32

* avx: _mm256_set_epi64x

* avx: _mm256_setr_pd, _mm256_setr_ps

* avx: _mm256_setr_epi8

* avx: _mm256_setr_epi16

* avx: _mm256_setr_epi32, _mm256_setr_epi64x

* avx: add missing assert_instr

* avx: _mm256_set1_pd

* avx: _mm256_set1_ps

* avx: _mm256_set1_epi8

* avx: _mm256_set1_epi16, _mm256_set1_epi32

* avx: _mm256_set1_epi64x

* avx: _mm256_castpd_si256, _mm256_castsi256_pd, _mm256_castps256_ps128, _mm256_castpd256_pd128, _mm256_castsi256_si128

* avx: remove assert_instr failing
dlrobertson pushed a commit to dlrobertson/rust that referenced this issue Nov 29, 2018
Improve Behaviour Considered Undefined section
eddyb pushed a commit to eddyb/rust that referenced this issue Jun 30, 2020
djtech-dev pushed a commit to djtech-dev/rust that referenced this issue Dec 9, 2021
Add context lifetime to most LLVM types for memory safety+
jaisnan pushed a commit to jaisnan/rust-dev that referenced this issue Oct 22, 2024
Towards model-checking#59

Changes
Added contracts for wrapping_shr (located in
library/core/src/num/int_macros.rs and uint_macros.rs)
Added harnesses for wrapping_shr of each integer type
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize --- 12
harnesses in total.
Revalidation
Per the discussion in
model-checking#59, we have to
build and run Kani from feature/verify-rust-std branch.
To revalidate the verification results, run the following command.
<harness_to_run> can be either num::verify to run all harnesses or
num::verify::<harness_name> (e.g. checked_wrapping_shl_i8) to run a
specific harness.
```
kani verify-std  "path/to/library" \
    --harness <harness_to_run> \
    -Z unstable-options \
    -Z function-contracts \
    -Z mem-predicates
```
All harnesses should pass the default checks (1251 checks where 1
unreachable).

```
SUMMARY:
 ** 0 of 161 failed (1 unreachable)

VERIFICATION:- SUCCESSFUL
Verification Time: 0.32086188s

Complete - 12 successfully verified harnesses, 0 failures, 12 total.
```

Example of the unreachable check:
```
Check 9: num::<impl i8>::wrapping_shr.assertion.1
	 - Status: UNREACHABLE
	 - Description: "attempt to subtract with overflow"
	 - Location: library/core/src/num/int_macros.rs:2199:42 in function num::<impl i8>::wrapping_shr
```

---------

Co-authored-by: Yenyun035 <yew005eng@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants