Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upUnsafe lifetime #1918
Conversation
jpernst
added some commits
Feb 21, 2017
This comment has been minimized.
This comment has been minimized.
|
I think it's worth considering how this feature interacts with unsafe code guidelines and affects the compiler optimizations (btw, is there any way to mention all the [unsafe code/memory model] group members?). I remember that @nikomatsakis showed that I have also a few questions about the detailed design: In this code, does the let raw: *const u8;
let r = unsafe { &*raw };
let slice = unsafe { std::slice::from_raw_parts(raw, 5) };If yes, then what about pub fn split_at_mut<'a>(&'a mut self, mid: usize) -> (&'a mut [T], &'a mut [T]) {
let copy: &mut [T] = unsafe { &mut *(self as *mut _) };
let left = &mut self[0..mid];
let right = &mut copy[mid..];
(left, right)
}And one more snippet: let uns: &'unsafe u8;
fn choose<'a>(_: &'a u8, _: &'a u8) -> &'a u8;
let x = 5;
let xref = &x; // xref: &'x u8
let r = choose(xref, uns);What's the lifetime of |
This comment has been minimized.
This comment has been minimized.
Storyyeller
commented
Feb 22, 2017
|
I don't think there's any need to omit dereferenceable. The use case for this is situations like Ref/rental/owning_ref where the logical lifetime is dynamic and hence can't be specified in Rust's type system, but the code ensures that the reference is valid whenever it is dereferenced at runtime. |
This comment has been minimized.
This comment has been minimized.
|
@krdln good food for thought. I'll ponder these some more and update my draft soon, but in the meantime, here are my initial thoughts: Per snippet 1, I'd say that, no, For snippet 2, if we assume that the input slice is explicitly of unsafe lifetime, then the compiler is free to choose any lifetime for As for the final example, the chosen lifetime should be As for optimization, I'm nowhere near an expert on this, so I'll defer to those with experience, but it seems reasonable to me that |
jpernst
added some commits
Feb 22, 2017
This comment has been minimized.
This comment has been minimized.
|
Added some detail about what precisely requires unsafe scope. I believe this should enable the scenarios it's intended to without any soundness holes, but it's entirely possible I've missed something. |
jpernst
added some commits
Feb 23, 2017
nrc
added
the
T-lang
label
Feb 23, 2017
aturon
assigned
nikomatsakis
Feb 23, 2017
jpernst
added some commits
Feb 23, 2017
This comment has been minimized.
This comment has been minimized.
|
It seems like what you're looking for is closer to If a lifetime called |
This comment has been minimized.
This comment has been minimized.
|
This rfc is somewhat weird, but it seems pretty neat anyway. I'm slightly divided. On one side, it seems to violate the invariants of the reference type. On the other, it cannot be created safely anyway. But well, I suspect the discussion will be dominated of discussion about invariants. |
This comment has been minimized.
This comment has been minimized.
|
@sgrif Currently in Rust, you can easily get a reference which requires unsafe to create, but not to dereference. It's just
If you're proposing You're right that in some cases
Also, I guess there are some usecases for |
This comment has been minimized.
This comment has been minimized.
|
@sgrif I went back and forth a bit on whether interacting with a But yes, the driving force behind this proposal is to be able to achieve a better API in rental. Currently this is impossible because the struct members I need to store are inexpressible. If there is a simpler, more minimal feature that will allow me to solve this, I'm absolutely open to it, but this proposal is the most limited I could come up with. I didn't just propose And as a more general point, I do think it's an important ability to be able to explicitly bypass borrowck if it's absolutely necessary to do so, and it's currently not possible to do that in cases other than reference types. |
This comment has been minimized.
This comment has been minimized.
Rufflewind
commented
Feb 27, 2017
|
The concept of I think the real problem here is that there is no way to tell the borrow checker to just ignore For this, it would be nice to have some way of deferring struct WrappedRef<'a, T>(Ref<'a, T> where T: 'a);This is very much like the implied bounds idea (see also rust-lang/rust#20671). To an outsider, the fn new<'a, 'b, T: 'a>(r: Ref<'a, T>) -> WrappedRef<'a, T> {
WrappedRef(r) // checks to make sure T: 'a
}After that, you can transmute This can obviously allow very dangerous violations of the trait system, but that’s what you get with |
This comment has been minimized.
This comment has been minimized.
|
@Rufflewind That's a fascinating idea and worth exploring, but I have reservations. My primary concern is that it involves creating intermediate wrapper types for any type that needs its constraints deferred, since it can't be done generically. I'll have to think more about the implications this would have for rental and how I'd incorporate it, but on first blush it feels like it would generate awkward boilerplate that somewhat obscures the intent. Extracting the proper bounds to attach to the inner field would also be challenging and would almost certainly require a proc-macro. Although, using a proc-macro is on the roadmap anyway. Personally I feel like |
This comment has been minimized.
This comment has been minimized.
|
In motivation, the workaround of SelfRefStruct makes it sounds like what you want is not struct SelfRefStruct<T> {
owner: RefCell<T>,
borrower: Ref<'lifetime_of(T), T>,
}(Yes I understand that |
This comment has been minimized.
This comment has been minimized.
|
@kennytm That's exactly what |
This comment has been minimized.
This comment has been minimized.
|
@eddyb I did consider suggesting |
This comment has been minimized.
This comment has been minimized.
|
@eddyb I assume The lifetime_of example is different from this, it extracts the concrete lifetime upper bound of T at monomorphization time, e.g. you cannot assign a |
This comment has been minimized.
This comment has been minimized.
Rufflewind
commented
Feb 27, 2017
•
|
I would say
Whatever choice you pick, it's clear that Edit: This also becomes a problem when you have a type with multiple |
This comment has been minimized.
This comment has been minimized.
Storyyeller
commented
Feb 27, 2017
|
I think the idea is that 'unsafe bounds would be confined within structs
and not exposed to users, so it is unlikely that you would have them in a
function signature in the first place.
…On Mon, Feb 27, 2017 at 12:31 PM, Phil Ruffwind ***@***.***> wrote:
I would say for<'a> is clearer, because the meaning of 'unsafe can become
ambiguous/confusing in some contexts. Consider say fn(R<'unsafe>): would
that mean
- for<'a> fn(R<'a>) or
- fn(for<'a> R<'a>)?
Whatever choice you pick, it's clear that 'unsafe is inherently a less
flexible solution than just enabling for<'a> in types.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#1918 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA9A-mwKwHmhqU_Z-N07_X663n5TG3Cdks5rgzKSgaJpZM4MIGef>
.
|
This comment has been minimized.
This comment has been minimized.
That's the same for |
This comment has been minimized.
This comment has been minimized.
|
I'd much prefer The second reason is that I think exists<'a> R<'a> |
This comment has been minimized.
This comment has been minimized.
|
@krdln That's the point, it's unsafe to lift to that (always longer or equal than reality) lifetime. As for existential lifetimes, they're just as unsafe unless you can link references to their allocations. |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
Rufflewind
commented
Feb 27, 2017
|
@krdln Although I think existential lifetimes are a great addition by themselves, their semantics are more like raw pointers (safe to construct, unsafe to use). In fact, I think (I personally think existential semantics are more appropriate here, as they prevent the dangerous possibility of accidental unification with |
This comment has been minimized.
This comment has been minimized.
|
Removed the section about general coercions into |
This comment has been minimized.
This comment has been minimized.
|
@Rufflewind I'm not opposed to existential semantics in principle, but I'm concerned about the practical design implications. IIRC they've been floated and postponed before, so I'm trying to avoid retreading that ground by sticking as closely to established semantics and precedent as possible. If those familiar with borrowck's implementation and the implications of existential semantics think it's doable, then I'm on board, but for now I'm trying to blaze the shortest, narrowest path to the expressiveness that I'm blocked on. |
This comment has been minimized.
This comment has been minimized.
|
Just as a note on the impetus behind this RFC: Just a few minutes ago I've fielded another support request for someone using one of my crates who wanted to store some of the structs it provides beside eachother in their own struct. This is currently inhibited by their lifetime parameters, and even rental can't yet solve it for that case, so my motivation remains strong. I've felt pressure and been tempted to relent and just use reference counting to eliminate the lifetime params, but I really don't want to just toss away a core benefit of rust to fix this issue. I am concerned, however, that this might be silently happening in the ecosystem already. Several APIs either provide RCed alternatives, or are simply just RCed to begin with, to avoid this issue. |
jpernst
added some commits
Feb 28, 2017
This comment has been minimized.
This comment has been minimized.
|
@rfcbot fcp postpone So, I think this RFC is addressing a genuine problem, but I feel like I would rather revisit this syntax when the unsafe-code-guidelines effort has progress a little further. In particular, I feel like some aspects of how unsafe code is written may change, and there may be additional semantics we would like from an I teetered a bit on this proposal, in that I also considered that it might be useful to merge the |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Mar 3, 2017
•
|
Team member @nikomatsakis has proposed to postpone this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
This comment has been minimized.
This comment has been minimized.
|
Waiting for the unsafe code guidelines before stabilization is perfectly reasonable and I support that, but I have one final plea for feature gating this sooner and allowing it to evolve. The immediate use of this feature will be to prototype a better library-level solution to the self-referential struct problem, and I have a few ideas on that front that I'd like to begin exploring. At this stage I can't fully envision the implications of the API for all scenarios or how it will interact with real world codebases, and there's no way to test it currently since the implementation for the API I'd like to expose cannot be written. I'm willing to follow along with the unsafe guidelines as they evolve and ensure my solution is fully conformant, in the interest of having a viable day 1 solution at such time as whatever final semantic form stabilizes. Either way, thanks to all for the consideration and discussion of this RFC. |
This comment has been minimized.
This comment has been minimized.
Storyyeller
commented
Mar 6, 2017
•
|
I found another crate that could use this: shawshank Currently, it uses the type signature |
This comment has been minimized.
This comment has been minimized.
|
My first reaction is "just use My second reaction is "oh, that's kind of gross, I see what the point of this is now". |
jpernst
referenced this pull request
Mar 15, 2017
Open
Possible utility of 'unsafe lifetime in memory model #37
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Apr 19, 2017
|
|
rfcbot
added
the
final-comment-period
label
Apr 19, 2017
This comment has been minimized.
This comment has been minimized.
Storyyeller
commented
Apr 22, 2017
|
Would it make sense to at least reserve |
This comment has been minimized.
This comment has been minimized.
|
@Storyyeller I thought all keywords were reserved in lifetime names, is that not the case? |
This comment has been minimized.
This comment has been minimized.
Storyyeller
commented
Apr 23, 2017
|
I didn't realize that. In that case, there's no problem. |
Rufflewind
referenced this pull request
Apr 24, 2017
Closed
There is no syntax for struct alignment #325
carols10cents
added this to FCP
in Tracker
Apr 26, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Apr 29, 2017
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
|
Closing as postponed. Thanks @jpernst! |
jpernst commentedFeb 22, 2017
Add a new special lifetime,
'unsafe, that implicitly satisfies any constraint, but may only be instantiated within an unsafe context. This lifetime is used in situations where the true lifetime of a value is otherwise inexpressible, and additionally serves as a warning to readers that handling of the value requires special care. As a result, unsafe code is no longer ever required to use misleading "false" or redundant lifetimes, instead clearly stating that the invariants are maintained by custom logic instead of borrowck.Rendered