@@ -24,6 +24,10 @@ use crate::{
2424 AsObject , Context , Py , PyObject , PyObjectRef , PyPayload , PyRef , PyResult , TryFromObject ,
2525} ;
2626use once_cell:: sync:: Lazy ;
27+ use rustpython_common:: {
28+ atomic:: { Ordering , PyAtomic , Radium } ,
29+ hash,
30+ } ;
2731use std:: { fmt, ops:: Deref } ;
2832
2933pub type SetContentType = dictdatatype:: Dict < ( ) > ;
@@ -71,9 +75,18 @@ impl PySet {
7175}
7276
7377#[ pyclass( module = false , name = "frozenset" , unhashable = true ) ]
74- #[ derive( Default ) ]
7578pub struct PyFrozenSet {
7679 inner : PySetInner ,
80+ hash : PyAtomic < PyHash > ,
81+ }
82+
83+ impl Default for PyFrozenSet {
84+ fn default ( ) -> Self {
85+ PyFrozenSet {
86+ inner : PySetInner :: default ( ) ,
87+ hash : hash:: SENTINEL . into ( ) ,
88+ }
89+ }
7790}
7891
7992impl PyFrozenSet {
@@ -87,7 +100,10 @@ impl PyFrozenSet {
87100 inner. add ( elem, vm) ?;
88101 }
89102 // FIXME: empty set check
90- Ok ( Self { inner } )
103+ Ok ( Self {
104+ inner,
105+ ..Default :: default ( )
106+ } )
91107 }
92108
93109 pub fn elements ( & self ) -> Vec < PyObjectRef > {
@@ -102,6 +118,7 @@ impl PyFrozenSet {
102118 ) -> PyResult < Self > {
103119 Ok ( Self {
104120 inner : self . inner . fold_op ( others, op, vm) ?,
121+ ..Default :: default ( )
105122 } )
106123 }
107124
@@ -115,6 +132,7 @@ impl PyFrozenSet {
115132 inner : self
116133 . inner
117134 . fold_op ( std:: iter:: once ( other. into_iterable ( vm) ?) , op, vm) ?,
135+ ..Default :: default ( )
118136 } )
119137 }
120138}
@@ -472,6 +490,7 @@ impl PySetInner {
472490 op (
473491 & PyFrozenSet {
474492 inner : set. inner . copy ( ) ,
493+ ..Default :: default ( )
475494 }
476495 . into_pyobject ( vm) ,
477496 vm,
@@ -956,6 +975,7 @@ impl PyFrozenSet {
956975 } else {
957976 Self {
958977 inner : zelf. inner . copy ( ) ,
978+ ..Default :: default ( )
959979 }
960980 . into_ref ( & vm. ctx )
961981 }
@@ -1057,6 +1077,7 @@ impl PyFrozenSet {
10571077 inner : other
10581078 . as_inner ( )
10591079 . difference ( ArgIterable :: try_from_object ( vm, zelf. into ( ) ) ?, vm) ?,
1080+ ..Default :: default ( )
10601081 } ) )
10611082 } else {
10621083 Ok ( PyArithmeticValue :: NotImplemented )
@@ -1107,7 +1128,23 @@ impl AsSequence for PyFrozenSet {
11071128impl Hashable for PyFrozenSet {
11081129 #[ inline]
11091130 fn hash ( zelf : & crate :: Py < Self > , vm : & VirtualMachine ) -> PyResult < PyHash > {
1110- zelf. inner . hash ( vm)
1131+ let hash = match zelf. hash . load ( Ordering :: Relaxed ) {
1132+ hash:: SENTINEL => {
1133+ let hash = zelf. inner . hash ( vm) ?;
1134+ match Radium :: compare_exchange (
1135+ & zelf. hash ,
1136+ hash:: SENTINEL ,
1137+ hash:: fix_sentinel ( hash) ,
1138+ Ordering :: Relaxed ,
1139+ Ordering :: Relaxed ,
1140+ ) {
1141+ Ok ( _) => hash,
1142+ Err ( prev_stored) => prev_stored,
1143+ }
1144+ }
1145+ hash => hash,
1146+ } ;
1147+ Ok ( hash)
11111148 }
11121149}
11131150
0 commit comments