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

Auto-dereferencing pointers #12704

Closed
Valloric opened this issue Mar 5, 2014 · 5 comments
Closed

Auto-dereferencing pointers #12704

Valloric opened this issue Mar 5, 2014 · 5 comments

Comments

@Valloric
Copy link
Contributor

Valloric commented Mar 5, 2014

Rust is awesome, but I've encountered a wrinkle.

let x: &u8 = &10;
let y = x == '\n' as u8;

This fails to compile because expected &u8 but found u8. Sigh, ok, fine, there's an easy workaround: *x == '\n' as u8.

Now let's look at this:

let x: u8 = 10;
let y = Some((1, &x));
let z = y == Some((1, '\n' as u8));

This fails for the same reason. The workaround is substantially more ugly now: y == Some((1, &('\n' as u8))).

But let's say you want to use assert_eq! instead of using equality directly because you're writing a test:

let x: u8 = 10;
let y = Some((1, &x));
assert_eq!(y, Some((1, &('\n' as u8))));

This just plain doesn't work because borrowed value doesn't live long enough.

And all of this seems very pointless to me. The compiler knows how a &T relates to a T and it knows it's safe to dereference the pointer because this is Rust and not C so why force the user to go through this ceremony (and that is the right word) of manually matching &T with &T and T with T? Why can't the compiler just Do The Right Thing™ here? It has all the information needed to not make my life harder for no reason.

In C and C++, an int* is effectively an Option<&int> (in Rust) because the pointer may be null so it can't be safely dereferenced. But this is Rust; we know the pointer is safe. Why not just deref it for the user? Why force the user to write convoluted code to placate the compiler and for what purpose?

I know Rust loves explicit casts but we should always examine the benefits of asking the user for such a cast. If it increases safety, great. That's what Rust is about. But I just don't see the win here, only a poor user experience for no gain.

@sfackler
Copy link
Member

sfackler commented Mar 5, 2014

I'm not sure this is a good idea. If this was implemented, it'd be impossible to determine what a line like this is doing without looking at the signature of foo:

x = foo();

@bharrisau
Copy link
Contributor

I think the intention was only to implement for binary operations. T binop &T automatically becomes T binop T by dereferencing one of the values. Feels like it promotes too much lazy.

@milibopp
Copy link
Contributor

milibopp commented Mar 5, 2014

It is probably relevant to consider that this suggestion does work for other operators, such as +:

let a = &3i64;
let b = a + 3i64;

Apart from that, comparing two different references with equal values amounts to true:

let a = &3i64;
let b = &3i64;
let c = a == b; // true

So, when &T == &T and T == T do the same thing and &T + T already works, it would be only consistent to have &T == T work. Or the other way around.

@Valloric
Copy link
Contributor Author

Valloric commented Mar 6, 2014

I think the question we should keep in mind is the following:

What benefit do we provide the user by forcing them to always deref pointers by hand?

Now think about that question for a minute. Give it some thought.

I'm not saying there is no benefit, just that I don't see it. The way I see it, we require input (derefing by hand and matching only &T with &T, not T) but don't provide a corresponding return on that input (safety or whatever). This is in contrast to other Rust features that require work from the developer. The borrow checker is a good example: pleasing it is often annoying, but the return on the work is immense (safety from data races etc) and thus totally worth it.

Note that we already auto-deref for method calls. From the tutorial:

let point = &~Point { x: 10.0, y: 20.0 };
println!("{:f}", point.x);

We don't force the user to write (*point).x because that's annoying.

I'm trying to point out that we've already decided to go down the auto-deref route at least in some places, but are holding back on doing it more widely for... I'm not entirely sure what reason. I'm afraid it has a lot to do with familiarity with C and C++ where one always has to deref pointers and we're just overly attached to that because of Stockholm syndrome.

Note that C++ has references that are pointers that can never be null (so the same feature as pointers in Rust[1]) and they are always dereferenced by default.

[1]: Just not implemented as well. Setting a C++ reference to NULL is possible, but provokes undefined behavior so far less safe than the Rust equivalent.

@Valloric
Copy link
Contributor Author

Valloric commented Jun 1, 2014

Now a Rust RFC: rust-lang/rfcs#102

@Valloric Valloric closed this as completed Jun 1, 2014
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 25, 2022
…chievink

internal: Use `SmallVec` to slightly shrink `ModPath` size

Saves like a megabyte on r-a itself.
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

4 participants