Guest User

Untitled

a guest
Nov 15th, 2018
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.79 KB | None | 0 0
  1. #![feature(pin)]
  2.  
  3. use std::pin::PinBox;
  4. use std::marker::Pinned;
  5. use std::ptr::NonNull;
  6.  
  7. // This is a self referencial struct since the slice field points to the data field.
  8. // We cannot inform the compiler about that with a normal reference,
  9. // since this pattern cannot be described with the usual borrowing rules.
  10. // Instead we use a raw pointer, though one which is known to not be null,
  11. // since we know it's pointing at the string.
  12. struct Unmovable {
  13. data: String,
  14. slice: NonNull<String>,
  15. _pin: Pinned,
  16. }
  17.  
  18. impl Unmovable {
  19. // To ensure the data doesn't move when the function returns,
  20. // we place it in the heap where it will stay for the lifetime of the object,
  21. // and the only way to access it would be through a pointer to it.
  22. fn new(data: String) -> PinBox<Self> {
  23. let res = Unmovable {
  24. data,
  25. // we only create the pointer once the data is in place
  26. // otherwise it will have already moved before we even started
  27. slice: NonNull::dangling(),
  28. _pin: Pinned,
  29. };
  30. let mut boxed = PinBox::new(res);
  31.  
  32. let slice = NonNull::from(&boxed.data);
  33. // we know this is safe because modifying a field doesn't move the whole struct
  34. unsafe { PinBox::get_mut(&mut boxed).slice = slice };
  35. boxed
  36. }
  37. }
  38. fn main() {
  39. let unmoved = Unmovable::new("hello".to_string());
  40. // The pointer should point to the correct location,
  41. // so long as the struct hasn't moved.
  42. // Meanwhile, we are free to move the pointer around.
  43. let mut still_unmoved = unmoved;
  44. assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
  45.  
  46. // Since our type doesn't implement Unpin, this will fail to compile:
  47. let new_unmoved = Unmovable::new("world".to_string());
  48. std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);
  49. }
Add Comment
Please, Sign In to add comment