-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Rename *T
to *const T
#68
Conversation
-1: I think that internal language consistency is more important than compatibility with C. |
is this helpful (or even essential?) for aliasing rules. i think i was told you dont need 'restrict' because safe code does that job (non-aliased mutable pointers). i think it would be confusing to flip mut->const, but then again, unsafe code is going to require special attention anyway. ( i had originally asked if you needed the opposite of 'restrict' or something like that, but this might be a solution ) |
@dobkeratops: This isn't related to |
ok so either way the rule would be unsafe pointers are assumed to potentially alias , i guess (be it mut/non mut or non const/const). |
In order to return |
I would prefer to have
I don't think it is possible to lint |
The type `&mut T` will automatically coerce to `*T` in the normal locations that | ||
coercion occurs today. It will also be possible to explicitly cast with an `as` | ||
expression. Additionally, the `&T` type will automatically coerce to `*const T`. | ||
Note that `&mut T` will not automatically coerce to `*const T`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there some motivation for this? &mut T
coerces to &T
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly just to remain the same as today's semantics with *T
and *mut T
. It doesn't seem like much could go wrong, but too many coercions may push us in the direction of implicit coercions between these two unsafe pointers, which I'd be a little worried about.
I don't have a huge preference one way or another on this (I'm fine amending it into the RFC)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think &mut
should coerce to *const
, and both conversions should be considered to consume the &mut
if they don't already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consumption may not work as intended, I believe you can continue to create &mut T
pointers via &mut *expr
(reborrowing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consumption may not work as intended, I believe you can continue to create &mut T pointers via &mut *expr (reborrowing).
If so, it still requires explicit thought & some actual code, rather than it happening automatically/implicitly.
If it turns out that trying to reconcile Rust and C semantics on unsafe #[no_mangle] extern fn memcpy(dst: #[cvqual(restrict)] *c_void,
src: #[cvqual(const, restrict)] *c_void,
n: size_t) -> *c_void; Of course, the compiler would have to learn how to handle the
|
This feels a better way to go than changing what *T currently means. |
I think I prefer the |
I don't see the evidence for the 'confusion' aspect. The vast majority of FFI code is (or should be) generated by rust-bindgen, which gets the As for the rest of Rust, I think the symmetry with all the other references explains how it's meant to be used. Notably, there's no consideration for the confusion between C++ references and our borrowed pointers which also have a flipped mutability. |
@SiegeLord that approach is actually mentioned under "Alternatives". :) |
I missed that, although I disagree that it's an 'alternative'. |
Without commenting on the RFC directly, @SiegeLord , I don't know how realistic it is to expect that we will ever arrive at a point where tools will obviate the need to write FFI code. Even today, there are plenty of people willingly avoiding rust-bindgen in favor of rolling their own wrappers by hand. If this RFC is accepted, count me among those who would prefer to have both |
@bstrie my thoughts exactly. It'd be great if we could automate it all away, but I think that's unlikely. |
We do need to get to the point where hard-wiring an ABI by hand is not required. Libraries often change the ABI between versions and it's not uncommon for an ABI to vary between platforms or different configurations of the library. At the moment, these changes will lead to silent memory corruption issues or worse. Since the remaining uses of raw pointers are native to Rust rather than for C wrappers, I think @SiegeLord's argument is a good one. |
Assuming you've meant bindings (stuff that goes inside |
BTW, rust-lang/rust#2124 is the issue for autogenerated bindings. |
@SiegeLord , I'm not the one you need to convince. :) I use bindgen, I love bindgen. It seems to be mostly graphics people who don't trust bindgen to not muck things up, but I'm not going to pretend that I have tons of evidence here. @thestinger , I thought you were campaigning for this change a while ago, before the RFC process existed. Have you reversed your position? Because if you don't think it's an issue, then I'll trust your judgment. |
@bstrie: I supported changing this before, but I'm less sure now. I don't really like the idea of making changes in I think part of the problem is that |
What about replacing the |
@bill-myers: What would be the name for the mutable one? |
@bill-myers I actually sorta like that. Maybe there's some consistency to be gained by following an axiom. Sorta the Smalltalk/Ruby way where "everything is an object". In Rust it could be "everything is an explicit named type" which is essentially true already, but just not expressed consistently. Some things are explicit like Part of me likes the sugar, because it's short-hand, but so much of the sugar has been removed/changed ( The most painful part of development for me is context switching. Following one convention, axiom consistently would make that easier and less all over the map like C++ is. @thestinger, |
I have updated this with |
How does this all relate to the issues around " |
@bharrisau I would say that this is a aliasing thing, though maybe not in the way you expected. We are not saying See e.g. http://yarchive.net/comp/const.html This is a crucial distinction between a const-qualified pointer To my mind, the advantage of using |
I'm a bit worried about this RFC. |
I am wary of dealing with I currently only know of You're right though, All-in-all, I personally feel like first-class language types are still necessary. These are the absolute core building blocks of all other primitives, which seems like they should have first-class support (even though they shouldn't be widely used). |
It has to be more important that Rust is consistent than similar to C. The idea of being a systems programming language also means dealing with hardware by itself, not relying on a 40+ year old language. FFI to C is only one use case for raw pointers. |
+1 @LeoTestard, I think in my humble experience of Rust. It's not a good idea to design rust with C in mind. C is well know for its complexity... Also the actual syntax is really good for reading code, it's clear and efficient. And to repond to @pnkfelix
Yes but it add all of the overhead in C about |
Sigh. Its not out of love for C that I contend that For example, If I thought that @darnuria I do not know what this:
is trying to say. Are you referring to syntactic overhead? Or are you talking about the fact that in C the declarations |
@pnkfelix: Sorry after reflection I was not clear.
By this statement I expressed the fact that C had a very different idea behind the // 1. In some way you have immutability to a value like in:
const char ch = 'c';
// 2. Imutability to a pointer like:
const char *str = "Toto";
// 3. Or a pointer to a pointer to const char:
const char **ptr_to_str = str;
// etc... And in this case 1. and are OK because it's not difficult to reason about them. But in the 3. case it's not clear to reason about it... Other point: Disclaimer: |
The current difference in Rust unsafe pointers types with C pointers types is | ||
proving to be too error prone to realistically enable these optimizations at a | ||
future date. By renaming Rust's unsafe pointers to closely match their C | ||
brethren, the likelihood for errneously transcribing a signature is diminished. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: s/errneously/erroneously/
@darnuria Your example translates directly to types one can describe already today in Rust, like so: fn main() {
#![allow(unused_mut)] // disable warnings to allow faithful transcription.
let ch : u8 = 'c' as u8;
let mut str1 : *u8 = "Toto".as_bytes().as_ptr();
let mut ptr_to_str : *mut *u8 = &mut str1 as *mut _;
unsafe {
printout(str1, ptr_to_str);
// **ptr_to_str = ch; // This would error with "cannot assign to ..."
// *str1 = ch; // and this would as well.
let mut but = ['U' as u8, 'h' as u8, 'O' as u8, 'h' as u8];
*ptr_to_str = but.as_ptr();
printout(str1, ptr_to_str);
but[0] = ch; // Accepted; `*str1` changes (`str1` does not, of
but[1] = '?' as u8; // course).`str1` is just like a `*const char` in C.
printout(str1, ptr_to_str);
}
fn printout(str1 : *u8, ptr_to_str: *mut *u8) {
unsafe {
println!("Hello str1[0, 1] {} str1: {:014} ptr_to_str: {}",
[*str1 as char, *str1.offset(1) as char].as_slice(),
str1,
ptr_to_str);
}
}
} What does this print? Depending on what addresses it allocates, it prints something like this:
If you think it is hard to reason about the type of My claim is that reasoning about the two cases is the same. We already support the notion of a |
I would suggest that if the best option on the merits is not obvious, backwards compatibility can be a tie breaker. In that respect, |
*mut T
, add *const T
*T
to *const T
ping @nikomatsakis, I updated with our discussion on Friday about when it is safe to coerce. I also added a new unresolved question about applying temporary lifetimes to coercions. |
|
||
When coercing from `&'a mut T` to `*mut T`, Rust will guarantee that the memory | ||
will stay valid during `'a` and that the memory will *not be accessed* during | ||
`'a`. Additionally, Rust will *consume* the `&'a mut T` during the coercion. It |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caveat: I am not sure if we currently consume during such a coercion. we should test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we don't, this code is accepted today:
extern {
fn bar(a: *mut int, b: *mut int);
}
unsafe fn foo(a: &mut int) {
bar(a, a)
}
Accepted as RFC 32. |
This does not yet change the compiler and libraries from `*T` to `*const T` as it will require a snapshot to do so. cc #7362 --- Note that the corresponding RFC, rust-lang/rfcs#68, has not yet been accepted. It was [discussed at the last meeting](https://github.com/rust-lang/rust/wiki/Meeting-weekly-2014-06-10#rfc-pr-68-unsafe-pointers-rename-t-to-const-t) and decided to be accepted, however. I figured I'd get started on the preliminary work for the RFC that will be required regardless.
This does not yet change the compiler and libraries from `*T` to `*const T` as it will require a snapshot to do so. cc #7362 --- Note that the corresponding RFC, rust-lang/rfcs#68, has not yet been accepted. It was [discussed at the last meeting](https://github.com/rust-lang/rust/wiki/Meeting-weekly-2014-06-10#rfc-pr-68-unsafe-pointers-rename-t-to-const-t) and decided to be accepted, however. I figured I'd get started on the preliminary work for the RFC that will be required regardless.
clarification about Stream::into_future()
Some context in rust-lang/rfcs#68
No description provided.