1 // Original work Copyright (c) 2014 The Rust Project Developers 2 // Modified work Copyright (c) 2016-2020 Nikita Pekin and the lazycell contributors 3 // See the README.md file at the top-level directory of this distribution. 4 // 5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8 // option. This file may not be copied, modified, or distributed 9 // except according to those terms. 10 11 #![cfg_attr(not(test), no_std)] 12 13 #![deny(missing_docs)] 14 #![cfg_attr(feature = "nightly", feature(plugin))] 15 #![cfg_attr(feature = "clippy", plugin(clippy))] 16 17 //! This crate provides a `LazyCell` struct which acts as a lazily filled 18 //! `Cell`. 19 //! 20 //! With a `RefCell`, the inner contents cannot be borrowed for the lifetime of 21 //! the entire object, but only of the borrows returned. A `LazyCell` is a 22 //! variation on `RefCell` which allows borrows to be tied to the lifetime of 23 //! the outer object. 24 //! 25 //! # Example 26 //! 27 //! The following example shows a quick example of the basic functionality of 28 //! `LazyCell`. 29 //! 30 //! ``` 31 //! use lazycell::LazyCell; 32 //! 33 //! let lazycell = LazyCell::new(); 34 //! 35 //! assert_eq!(lazycell.borrow(), None); 36 //! assert!(!lazycell.filled()); 37 //! lazycell.fill(1).ok(); 38 //! assert!(lazycell.filled()); 39 //! assert_eq!(lazycell.borrow(), Some(&1)); 40 //! assert_eq!(lazycell.into_inner(), Some(1)); 41 //! ``` 42 //! 43 //! `AtomicLazyCell` is a variant that uses an atomic variable to manage 44 //! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell` 45 //! is that after it is initialized, it can't be modified. 46 47 48 // ANDROID: Unconditionally use std to allow building as a dylib. 49 #[cfg(not(test))] 50 #[macro_use] 51 extern crate std; 52 #[cfg(feature = "serde")] 53 extern crate serde; 54 55 #[cfg(feature = "serde")] 56 mod serde_impl; 57 58 use std::cell::UnsafeCell; 59 use std::mem; 60 use std::sync::atomic::{AtomicUsize, Ordering}; 61 62 /// A lazily filled `Cell`, with mutable contents. 63 /// 64 /// A `LazyCell` is completely frozen once filled, **unless** you have `&mut` 65 /// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the 66 /// contents. 67 #[derive(Debug)] 68 pub struct LazyCell<T> { 69 inner: UnsafeCell<Option<T>>, 70 } 71 72 impl<T> LazyCell<T> { 73 /// Creates a new, empty, `LazyCell`. new() -> LazyCell<T>74 pub fn new() -> LazyCell<T> { 75 LazyCell { inner: UnsafeCell::new(None) } 76 } 77 78 /// Put a value into this cell. 79 /// 80 /// This function will return `Err(value)` if the cell is already full. fill(&self, value: T) -> Result<(), T>81 pub fn fill(&self, value: T) -> Result<(), T> { 82 let slot = unsafe { &*self.inner.get() }; 83 if slot.is_some() { 84 return Err(value); 85 } 86 let slot = unsafe { &mut *self.inner.get() }; 87 *slot = Some(value); 88 89 Ok(()) 90 } 91 92 /// Put a value into this cell. 93 /// 94 /// Note that this function is infallible but requires `&mut self`. By 95 /// requiring `&mut self` we're guaranteed that no active borrows to this 96 /// cell can exist so we can always fill in the value. This may not always 97 /// be usable, however, as `&mut self` may not be possible to borrow. 98 /// 99 /// # Return value 100 /// 101 /// This function returns the previous value, if any. replace(&mut self, value: T) -> Option<T>102 pub fn replace(&mut self, value: T) -> Option<T> { 103 mem::replace(unsafe { &mut *self.inner.get() }, Some(value)) 104 } 105 106 /// Test whether this cell has been previously filled. filled(&self) -> bool107 pub fn filled(&self) -> bool { 108 self.borrow().is_some() 109 } 110 111 /// Borrows the contents of this lazy cell for the duration of the cell 112 /// itself. 113 /// 114 /// This function will return `Some` if the cell has been previously 115 /// initialized, and `None` if it has not yet been initialized. borrow(&self) -> Option<&T>116 pub fn borrow(&self) -> Option<&T> { 117 unsafe { &*self.inner.get() }.as_ref() 118 } 119 120 /// Borrows the contents of this lazy cell mutably for the duration of the cell 121 /// itself. 122 /// 123 /// This function will return `Some` if the cell has been previously 124 /// initialized, and `None` if it has not yet been initialized. borrow_mut(&mut self) -> Option<&mut T>125 pub fn borrow_mut(&mut self) -> Option<&mut T> { 126 unsafe { &mut *self.inner.get() }.as_mut() 127 } 128 129 /// Borrows the contents of this lazy cell for the duration of the cell 130 /// itself. 131 /// 132 /// If the cell has not yet been filled, the cell is first filled using the 133 /// function provided. 134 /// 135 /// # Panics 136 /// 137 /// Panics if the cell becomes filled as a side effect of `f`. borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T138 pub fn borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T { 139 if let Some(value) = self.borrow() { 140 return value; 141 } 142 let value = f(); 143 if self.fill(value).is_err() { 144 panic!("borrow_with: cell was filled by closure") 145 } 146 self.borrow().unwrap() 147 } 148 149 /// Borrows the contents of this `LazyCell` mutably for the duration of the 150 /// cell itself. 151 /// 152 /// If the cell has not yet been filled, the cell is first filled using the 153 /// function provided. 154 /// 155 /// # Panics 156 /// 157 /// Panics if the cell becomes filled as a side effect of `f`. borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T158 pub fn borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T { 159 if !self.filled() { 160 let value = f(); 161 if self.fill(value).is_err() { 162 panic!("borrow_mut_with: cell was filled by closure") 163 } 164 } 165 166 self.borrow_mut().unwrap() 167 } 168 169 /// Same as `borrow_with`, but allows the initializing function to fail. 170 /// 171 /// # Panics 172 /// 173 /// Panics if the cell becomes filled as a side effect of `f`. try_borrow_with<E, F>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>174 pub fn try_borrow_with<E, F>(&self, f: F) -> Result<&T, E> 175 where F: FnOnce() -> Result<T, E> 176 { 177 if let Some(value) = self.borrow() { 178 return Ok(value); 179 } 180 let value = f()?; 181 if self.fill(value).is_err() { 182 panic!("try_borrow_with: cell was filled by closure") 183 } 184 Ok(self.borrow().unwrap()) 185 } 186 187 /// Same as `borrow_mut_with`, but allows the initializing function to fail. 188 /// 189 /// # Panics 190 /// 191 /// Panics if the cell becomes filled as a side effect of `f`. try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E> where F: FnOnce() -> Result<T, E>192 pub fn try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E> 193 where F: FnOnce() -> Result<T, E> 194 { 195 if self.filled() { 196 return Ok(self.borrow_mut().unwrap()); 197 } 198 let value = f()?; 199 if self.fill(value).is_err() { 200 panic!("try_borrow_mut_with: cell was filled by closure") 201 } 202 Ok(self.borrow_mut().unwrap()) 203 } 204 205 /// Consumes this `LazyCell`, returning the underlying value. into_inner(self) -> Option<T>206 pub fn into_inner(self) -> Option<T> { 207 // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe 208 // function. This unsafe can be removed when supporting Rust older than 209 // 1.25 is not needed. 210 #[allow(unused_unsafe)] 211 unsafe { self.inner.into_inner() } 212 } 213 } 214 215 impl<T: Copy> LazyCell<T> { 216 /// Returns a copy of the contents of the lazy cell. 217 /// 218 /// This function will return `Some` if the cell has been previously initialized, 219 /// and `None` if it has not yet been initialized. get(&self) -> Option<T>220 pub fn get(&self) -> Option<T> { 221 unsafe { *self.inner.get() } 222 } 223 } 224 225 impl<T> Default for LazyCell<T> { default() -> Self226 fn default() -> Self { 227 Self::new() 228 } 229 } 230 231 impl <T: Clone> Clone for LazyCell<T> { 232 /// Create a clone of this `LazyCell` 233 /// 234 /// If self has not been initialized, returns an uninitialized `LazyCell` 235 /// otherwise returns a `LazyCell` already initialized with a clone of the 236 /// contents of self. clone(&self) -> LazyCell<T>237 fn clone(&self) -> LazyCell<T> { 238 LazyCell { inner: UnsafeCell::new(self.borrow().map(Clone::clone) ) } 239 } 240 } 241 242 // Tracks the AtomicLazyCell inner state 243 const NONE: usize = 0; 244 const LOCK: usize = 1; 245 const SOME: usize = 2; 246 247 /// A lazily filled and thread-safe `Cell`, with frozen contents. 248 #[derive(Debug)] 249 pub struct AtomicLazyCell<T> { 250 inner: UnsafeCell<Option<T>>, 251 state: AtomicUsize, 252 } 253 254 impl<T> AtomicLazyCell<T> { 255 /// An empty `AtomicLazyCell`. 256 pub const NONE: Self = Self { 257 inner: UnsafeCell::new(None), 258 state: AtomicUsize::new(NONE), 259 }; 260 261 /// Creates a new, empty, `AtomicLazyCell`. new() -> AtomicLazyCell<T>262 pub fn new() -> AtomicLazyCell<T> { 263 Self::NONE 264 } 265 266 /// Put a value into this cell. 267 /// 268 /// This function will return `Err(value)` if the cell is already full. fill(&self, t: T) -> Result<(), T>269 pub fn fill(&self, t: T) -> Result<(), T> { 270 if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) { 271 return Err(t); 272 } 273 274 unsafe { *self.inner.get() = Some(t) }; 275 276 if LOCK != self.state.compare_and_swap(LOCK, SOME, Ordering::Release) { 277 panic!("unable to release lock"); 278 } 279 280 Ok(()) 281 } 282 283 /// Put a value into this cell. 284 /// 285 /// Note that this function is infallible but requires `&mut self`. By 286 /// requiring `&mut self` we're guaranteed that no active borrows to this 287 /// cell can exist so we can always fill in the value. This may not always 288 /// be usable, however, as `&mut self` may not be possible to borrow. 289 /// 290 /// # Return value 291 /// 292 /// This function returns the previous value, if any. replace(&mut self, value: T) -> Option<T>293 pub fn replace(&mut self, value: T) -> Option<T> { 294 match mem::replace(self.state.get_mut(), SOME) { 295 NONE | SOME => {} 296 _ => panic!("cell in inconsistent state"), 297 } 298 mem::replace(unsafe { &mut *self.inner.get() }, Some(value)) 299 } 300 301 /// Test whether this cell has been previously filled. filled(&self) -> bool302 pub fn filled(&self) -> bool { 303 self.state.load(Ordering::Acquire) == SOME 304 } 305 306 /// Borrows the contents of this lazy cell for the duration of the cell 307 /// itself. 308 /// 309 /// This function will return `Some` if the cell has been previously 310 /// initialized, and `None` if it has not yet been initialized. borrow(&self) -> Option<&T>311 pub fn borrow(&self) -> Option<&T> { 312 match self.state.load(Ordering::Acquire) { 313 SOME => unsafe { &*self.inner.get() }.as_ref(), 314 _ => None, 315 } 316 } 317 318 /// Consumes this `LazyCell`, returning the underlying value. into_inner(self) -> Option<T>319 pub fn into_inner(self) -> Option<T> { 320 // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe 321 // function. This unsafe can be removed when supporting Rust older than 322 // 1.25 is not needed. 323 #[allow(unused_unsafe)] 324 unsafe { self.inner.into_inner() } 325 } 326 } 327 328 impl<T: Copy> AtomicLazyCell<T> { 329 /// Returns a copy of the contents of the lazy cell. 330 /// 331 /// This function will return `Some` if the cell has been previously initialized, 332 /// and `None` if it has not yet been initialized. get(&self) -> Option<T>333 pub fn get(&self) -> Option<T> { 334 match self.state.load(Ordering::Acquire) { 335 SOME => unsafe { *self.inner.get() }, 336 _ => None, 337 } 338 } 339 } 340 341 impl<T> Default for AtomicLazyCell<T> { default() -> Self342 fn default() -> Self { 343 Self::new() 344 } 345 } 346 347 impl<T: Clone> Clone for AtomicLazyCell<T> { 348 /// Create a clone of this `AtomicLazyCell` 349 /// 350 /// If self has not been initialized, returns an uninitialized `AtomicLazyCell` 351 /// otherwise returns an `AtomicLazyCell` already initialized with a clone of the 352 /// contents of self. clone(&self) -> AtomicLazyCell<T>353 fn clone(&self) -> AtomicLazyCell<T> { 354 self.borrow().map_or( 355 Self::NONE, 356 |v| AtomicLazyCell { 357 inner: UnsafeCell::new(Some(v.clone())), 358 state: AtomicUsize::new(SOME), 359 } 360 ) 361 } 362 } 363 364 unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {} 365 366 unsafe impl<T: Send> Send for AtomicLazyCell<T> {} 367 368 #[cfg(test)] 369 mod tests { 370 use super::{AtomicLazyCell, LazyCell}; 371 372 #[test] test_borrow_from_empty()373 fn test_borrow_from_empty() { 374 let lazycell: LazyCell<usize> = LazyCell::new(); 375 376 let value = lazycell.borrow(); 377 assert_eq!(value, None); 378 379 let value = lazycell.get(); 380 assert_eq!(value, None); 381 } 382 383 #[test] test_fill_and_borrow()384 fn test_fill_and_borrow() { 385 let lazycell = LazyCell::new(); 386 387 assert!(!lazycell.filled()); 388 lazycell.fill(1).unwrap(); 389 assert!(lazycell.filled()); 390 391 let value = lazycell.borrow(); 392 assert_eq!(value, Some(&1)); 393 394 let value = lazycell.get(); 395 assert_eq!(value, Some(1)); 396 } 397 398 #[test] test_borrow_mut()399 fn test_borrow_mut() { 400 let mut lazycell = LazyCell::new(); 401 assert!(lazycell.borrow_mut().is_none()); 402 403 lazycell.fill(1).unwrap(); 404 assert_eq!(lazycell.borrow_mut(), Some(&mut 1)); 405 406 *lazycell.borrow_mut().unwrap() = 2; 407 assert_eq!(lazycell.borrow_mut(), Some(&mut 2)); 408 409 // official way to reset the cell 410 lazycell = LazyCell::new(); 411 assert!(lazycell.borrow_mut().is_none()); 412 } 413 414 #[test] test_already_filled_error()415 fn test_already_filled_error() { 416 let lazycell = LazyCell::new(); 417 418 lazycell.fill(1).unwrap(); 419 assert_eq!(lazycell.fill(1), Err(1)); 420 } 421 422 #[test] test_borrow_with()423 fn test_borrow_with() { 424 let lazycell = LazyCell::new(); 425 426 let value = lazycell.borrow_with(|| 1); 427 assert_eq!(&1, value); 428 } 429 430 #[test] test_borrow_with_already_filled()431 fn test_borrow_with_already_filled() { 432 let lazycell = LazyCell::new(); 433 lazycell.fill(1).unwrap(); 434 435 let value = lazycell.borrow_with(|| 1); 436 assert_eq!(&1, value); 437 } 438 439 #[test] test_borrow_with_not_called_when_filled()440 fn test_borrow_with_not_called_when_filled() { 441 let lazycell = LazyCell::new(); 442 443 lazycell.fill(1).unwrap(); 444 445 let value = lazycell.borrow_with(|| 2); 446 assert_eq!(&1, value); 447 } 448 449 #[test] 450 #[should_panic] test_borrow_with_sound_with_reentrancy()451 fn test_borrow_with_sound_with_reentrancy() { 452 // Kudos to dbaupp for discovering this issue 453 // https://www.reddit.com/r/rust/comments/5vs9rt/lazycell_a_rust_library_providing_a_lazilyfilled/de527xm/ 454 let lazycell: LazyCell<Box<i32>> = LazyCell::new(); 455 456 let mut reference: Option<&i32> = None; 457 458 lazycell.borrow_with(|| { 459 let _ = lazycell.fill(Box::new(1)); 460 reference = lazycell.borrow().map(|r| &**r); 461 Box::new(2) 462 }); 463 } 464 465 #[test] test_borrow_mut_with()466 fn test_borrow_mut_with() { 467 let mut lazycell = LazyCell::new(); 468 469 { 470 let value = lazycell.borrow_mut_with(|| 1); 471 assert_eq!(&mut 1, value); 472 *value = 2; 473 } 474 assert_eq!(&2, lazycell.borrow().unwrap()); 475 } 476 477 #[test] test_borrow_mut_with_already_filled()478 fn test_borrow_mut_with_already_filled() { 479 let mut lazycell = LazyCell::new(); 480 lazycell.fill(1).unwrap(); 481 482 let value = lazycell.borrow_mut_with(|| 1); 483 assert_eq!(&1, value); 484 } 485 486 #[test] test_borrow_mut_with_not_called_when_filled()487 fn test_borrow_mut_with_not_called_when_filled() { 488 let mut lazycell = LazyCell::new(); 489 490 lazycell.fill(1).unwrap(); 491 492 let value = lazycell.borrow_mut_with(|| 2); 493 assert_eq!(&1, value); 494 } 495 496 #[test] test_try_borrow_with_ok()497 fn test_try_borrow_with_ok() { 498 let lazycell = LazyCell::new(); 499 let result = lazycell.try_borrow_with::<(), _>(|| Ok(1)); 500 assert_eq!(result, Ok(&1)); 501 } 502 503 #[test] test_try_borrow_with_err()504 fn test_try_borrow_with_err() { 505 let lazycell = LazyCell::<()>::new(); 506 let result = lazycell.try_borrow_with(|| Err(1)); 507 assert_eq!(result, Err(1)); 508 } 509 510 #[test] test_try_borrow_with_already_filled()511 fn test_try_borrow_with_already_filled() { 512 let lazycell = LazyCell::new(); 513 lazycell.fill(1).unwrap(); 514 let result = lazycell.try_borrow_with::<(), _>(|| unreachable!()); 515 assert_eq!(result, Ok(&1)); 516 } 517 518 #[test] 519 #[should_panic] test_try_borrow_with_sound_with_reentrancy()520 fn test_try_borrow_with_sound_with_reentrancy() { 521 let lazycell: LazyCell<Box<i32>> = LazyCell::new(); 522 523 let mut reference: Option<&i32> = None; 524 525 let _ = lazycell.try_borrow_with::<(), _>(|| { 526 let _ = lazycell.fill(Box::new(1)); 527 reference = lazycell.borrow().map(|r| &**r); 528 Ok(Box::new(2)) 529 }); 530 } 531 532 #[test] test_try_borrow_mut_with_ok()533 fn test_try_borrow_mut_with_ok() { 534 let mut lazycell = LazyCell::new(); 535 { 536 let result = lazycell.try_borrow_mut_with::<(), _>(|| Ok(1)); 537 assert_eq!(result, Ok(&mut 1)); 538 *result.unwrap() = 2; 539 } 540 assert_eq!(&mut 2, lazycell.borrow().unwrap()); 541 } 542 543 #[test] test_try_borrow_mut_with_err()544 fn test_try_borrow_mut_with_err() { 545 let mut lazycell = LazyCell::<()>::new(); 546 let result = lazycell.try_borrow_mut_with(|| Err(1)); 547 assert_eq!(result, Err(1)); 548 } 549 550 #[test] test_try_borrow_mut_with_already_filled()551 fn test_try_borrow_mut_with_already_filled() { 552 let mut lazycell = LazyCell::new(); 553 lazycell.fill(1).unwrap(); 554 let result = lazycell.try_borrow_mut_with::<(), _>(|| unreachable!()); 555 assert_eq!(result, Ok(&mut 1)); 556 } 557 558 #[test] test_into_inner()559 fn test_into_inner() { 560 let lazycell = LazyCell::new(); 561 562 lazycell.fill(1).unwrap(); 563 let value = lazycell.into_inner(); 564 assert_eq!(value, Some(1)); 565 } 566 567 #[test] test_atomic_borrow_from_empty()568 fn test_atomic_borrow_from_empty() { 569 let lazycell: AtomicLazyCell<usize> = AtomicLazyCell::new(); 570 571 let value = lazycell.borrow(); 572 assert_eq!(value, None); 573 574 let value = lazycell.get(); 575 assert_eq!(value, None); 576 } 577 578 #[test] test_atomic_fill_and_borrow()579 fn test_atomic_fill_and_borrow() { 580 let lazycell = AtomicLazyCell::new(); 581 582 assert!(!lazycell.filled()); 583 lazycell.fill(1).unwrap(); 584 assert!(lazycell.filled()); 585 586 let value = lazycell.borrow(); 587 assert_eq!(value, Some(&1)); 588 589 let value = lazycell.get(); 590 assert_eq!(value, Some(1)); 591 } 592 593 #[test] test_atomic_already_filled_panic()594 fn test_atomic_already_filled_panic() { 595 let lazycell = AtomicLazyCell::new(); 596 597 lazycell.fill(1).unwrap(); 598 assert_eq!(1, lazycell.fill(1).unwrap_err()); 599 } 600 601 #[test] test_atomic_into_inner()602 fn test_atomic_into_inner() { 603 let lazycell = AtomicLazyCell::new(); 604 605 lazycell.fill(1).unwrap(); 606 let value = lazycell.into_inner(); 607 assert_eq!(value, Some(1)); 608 } 609 610 #[test] normal_replace()611 fn normal_replace() { 612 let mut cell = LazyCell::new(); 613 assert_eq!(cell.fill(1), Ok(())); 614 assert_eq!(cell.replace(2), Some(1)); 615 assert_eq!(cell.replace(3), Some(2)); 616 assert_eq!(cell.borrow(), Some(&3)); 617 618 let mut cell = LazyCell::new(); 619 assert_eq!(cell.replace(2), None); 620 } 621 622 #[test] atomic_replace()623 fn atomic_replace() { 624 let mut cell = AtomicLazyCell::new(); 625 assert_eq!(cell.fill(1), Ok(())); 626 assert_eq!(cell.replace(2), Some(1)); 627 assert_eq!(cell.replace(3), Some(2)); 628 assert_eq!(cell.borrow(), Some(&3)); 629 } 630 631 #[test] clone()632 fn clone() { 633 let mut cell = LazyCell::new(); 634 let clone1 = cell.clone(); 635 assert_eq!(clone1.borrow(), None); 636 assert_eq!(cell.fill(1), Ok(())); 637 let mut clone2 = cell.clone(); 638 assert_eq!(clone1.borrow(), None); 639 assert_eq!(clone2.borrow(), Some(&1)); 640 assert_eq!(cell.replace(2), Some(1)); 641 assert_eq!(clone1.borrow(), None); 642 assert_eq!(clone2.borrow(), Some(&1)); 643 assert_eq!(clone1.fill(3), Ok(())); 644 assert_eq!(clone2.replace(4), Some(1)); 645 assert_eq!(clone1.borrow(), Some(&3)); 646 assert_eq!(clone2.borrow(), Some(&4)); 647 assert_eq!(cell.borrow(), Some(&2)); 648 } 649 650 #[test] clone_atomic()651 fn clone_atomic() { 652 let mut cell = AtomicLazyCell::new(); 653 let clone1 = cell.clone(); 654 assert_eq!(clone1.borrow(), None); 655 assert_eq!(cell.fill(1), Ok(())); 656 let mut clone2 = cell.clone(); 657 assert_eq!(clone1.borrow(), None); 658 assert_eq!(clone2.borrow(), Some(&1)); 659 assert_eq!(cell.replace(2), Some(1)); 660 assert_eq!(clone1.borrow(), None); 661 assert_eq!(clone2.borrow(), Some(&1)); 662 assert_eq!(clone1.fill(3), Ok(())); 663 assert_eq!(clone2.replace(4), Some(1)); 664 assert_eq!(clone1.borrow(), Some(&3)); 665 assert_eq!(clone2.borrow(), Some(&4)); 666 assert_eq!(cell.borrow(), Some(&2)); 667 } 668 669 #[test] default()670 fn default() { 671 #[derive(Default)] 672 struct Defaultable; 673 struct NonDefaultable; 674 675 let _: LazyCell<Defaultable> = LazyCell::default(); 676 let _: LazyCell<NonDefaultable> = LazyCell::default(); 677 678 let _: AtomicLazyCell<Defaultable> = AtomicLazyCell::default(); 679 let _: AtomicLazyCell<NonDefaultable> = AtomicLazyCell::default(); 680 } 681 } 682