@@ -24,6 +24,10 @@ use crate::{
24
24
AsObject , Context , Py , PyObject , PyObjectRef , PyPayload , PyRef , PyResult , TryFromObject ,
25
25
} ;
26
26
use once_cell:: sync:: Lazy ;
27
+ use rustpython_common:: {
28
+ atomic:: { Ordering , PyAtomic , Radium } ,
29
+ hash,
30
+ } ;
27
31
use std:: { fmt, ops:: Deref } ;
28
32
29
33
pub type SetContentType = dictdatatype:: Dict < ( ) > ;
@@ -71,9 +75,18 @@ impl PySet {
71
75
}
72
76
73
77
#[ pyclass( module = false , name = "frozenset" , unhashable = true ) ]
74
- #[ derive( Default ) ]
75
78
pub struct PyFrozenSet {
76
79
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
+ }
77
90
}
78
91
79
92
impl PyFrozenSet {
@@ -87,7 +100,10 @@ impl PyFrozenSet {
87
100
inner. add ( elem, vm) ?;
88
101
}
89
102
// FIXME: empty set check
90
- Ok ( Self { inner } )
103
+ Ok ( Self {
104
+ inner,
105
+ ..Default :: default ( )
106
+ } )
91
107
}
92
108
93
109
pub fn elements ( & self ) -> Vec < PyObjectRef > {
@@ -102,6 +118,7 @@ impl PyFrozenSet {
102
118
) -> PyResult < Self > {
103
119
Ok ( Self {
104
120
inner : self . inner . fold_op ( others, op, vm) ?,
121
+ ..Default :: default ( )
105
122
} )
106
123
}
107
124
@@ -115,6 +132,7 @@ impl PyFrozenSet {
115
132
inner : self
116
133
. inner
117
134
. fold_op ( std:: iter:: once ( other. into_iterable ( vm) ?) , op, vm) ?,
135
+ ..Default :: default ( )
118
136
} )
119
137
}
120
138
}
@@ -472,6 +490,7 @@ impl PySetInner {
472
490
op (
473
491
& PyFrozenSet {
474
492
inner : set. inner . copy ( ) ,
493
+ ..Default :: default ( )
475
494
}
476
495
. into_pyobject ( vm) ,
477
496
vm,
@@ -956,6 +975,7 @@ impl PyFrozenSet {
956
975
} else {
957
976
Self {
958
977
inner : zelf. inner . copy ( ) ,
978
+ ..Default :: default ( )
959
979
}
960
980
. into_ref ( & vm. ctx )
961
981
}
@@ -1057,6 +1077,7 @@ impl PyFrozenSet {
1057
1077
inner : other
1058
1078
. as_inner ( )
1059
1079
. difference ( ArgIterable :: try_from_object ( vm, zelf. into ( ) ) ?, vm) ?,
1080
+ ..Default :: default ( )
1060
1081
} ) )
1061
1082
} else {
1062
1083
Ok ( PyArithmeticValue :: NotImplemented )
@@ -1107,7 +1128,23 @@ impl AsSequence for PyFrozenSet {
1107
1128
impl Hashable for PyFrozenSet {
1108
1129
#[ inline]
1109
1130
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)
1111
1148
}
1112
1149
}
1113
1150
0 commit comments