File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1776,7 +1776,7 @@ impl<T> Option<T> {
17761776 #[ rustc_const_unstable ( feature = "const_option_ops" , issue = "143956" ) ]
17771777 pub const fn get_or_insert_default( & mut self ) -> & mut T
17781778 where
1779- T : [ const ] Default + [ const ] Destruct ,
1779+ T : [ const ] Default ,
17801780 {
17811781 self . get_or_insert_with ( T :: default)
17821782 }
@@ -1804,10 +1804,20 @@ impl<T> Option<T> {
18041804 pub const fn get_or_insert_with< F > ( & mut self , f : F ) -> & mut T
18051805 where
18061806 F : [ const ] FnOnce ( ) -> T + [ const ] Destruct ,
1807- T : [ const ] Destruct ,
18081807 {
18091808 if let None = self {
1810- * self = Some ( f ( ) ) ;
1809+ // The effect of this is identical to
1810+ // *self = Some(f());
1811+ // except that it does not drop the old value of `*self`. This is not a leak, because
1812+ // we just checked that the old value is `None`, which contains no fields to drop.
1813+ //
1814+ // This implementation strategy avoids needing a `T: [const] Destruct` bound, and avoids
1815+ // possibly compiling needless drop code (as would sometimes happen in the previous
1816+ // implementation).
1817+ //
1818+ // It could also be expressed as `unsafe { core::ptr::write(self, Some(f())) }`, but
1819+ // no reason is currently known to use additional unsafe code here.
1820+ mem:: forget ( mem:: replace ( self , Some ( f ( ) ) ) ) ;
18111821 }
18121822
18131823 // SAFETY: a `None` variant for `self` would have been replaced by a `Some`
Original file line number Diff line number Diff line change @@ -495,6 +495,30 @@ const fn option_const_mut() {
495495 */
496496}
497497
498+ /// Test that `Option::get_or_insert_default` is usable in const contexts, including with types that
499+ /// do not satisfy `T: const Destruct`.
500+ #[ test]
501+ fn const_get_or_insert_default ( ) {
502+ const OPT_DEFAULT : Option < Vec < bool > > = {
503+ let mut x = None ;
504+ x. get_or_insert_default ( ) ;
505+ x
506+ } ;
507+ assert ! ( OPT_DEFAULT . is_some( ) ) ;
508+ }
509+
510+ /// Test that `Option::get_or_insert_with` is usable in const contexts, including with types that
511+ /// do not satisfy `T: const Destruct`.
512+ #[ test]
513+ fn const_get_or_insert_with ( ) {
514+ const OPT_WITH : Option < Vec < bool > > = {
515+ let mut x = None ;
516+ x. get_or_insert_with ( Vec :: new) ;
517+ x
518+ } ;
519+ assert ! ( OPT_WITH . is_some( ) ) ;
520+ }
521+
498522#[ test]
499523fn test_unwrap_drop ( ) {
500524 struct Dtor < ' a > {
You can’t perform that action at this time.
0 commit comments