• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mattwparas / steel / 19642897388

24 Nov 2025 05:14PM UTC coverage: 49.283% (-0.03%) from 49.314%
19642897388

Pull #574

github

web-flow
Merge fde67cc60 into ed9e0c34e
Pull Request #574: Add bitwise operators and hash code function

7 of 51 new or added lines in 3 files covered. (13.73%)

66 existing lines in 5 files now uncovered.

15943 of 32350 relevant lines covered (49.28%)

3471369.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.67
/crates/steel-core/src/values/lists.rs
1
use std::cell::Cell;
2

3
use im_lists::{
4
    handler::{DefaultDropHandler, DropHandler},
5
    shared::PointerFamily,
6
};
7

8
use crate::{
9
    gc::Gc,
10
    rvals::{FromSteelVal, IntoSteelVal},
11
    SteelVal,
12
};
13

14
// TODO:
15
// Builtin immutable pairs
16
#[derive(Clone, Hash)]
17
pub struct Pair {
18
    pub(crate) car: SteelVal,
19
    pub(crate) cdr: SteelVal,
20
}
21

22
impl Pair {
UNCOV
23
    pub fn cons(car: SteelVal, cdr: SteelVal) -> Self {
×
24
        Pair { car, cdr }
25
    }
26

27
    pub fn car(&self) -> SteelVal {
59,452✔
28
        self.car.clone()
118,904✔
29
    }
30

31
    pub fn cdr(&self) -> SteelVal {
12,621✔
32
        self.cdr.clone()
25,242✔
33
    }
34

35
    pub fn car_ref(&self) -> &SteelVal {
25✔
36
        &self.car
25✔
37
    }
38

39
    pub fn cdr_ref(&self) -> &SteelVal {
25✔
40
        &self.cdr
25✔
41
    }
42
}
43

44
impl From<Pair> for SteelVal {
45
    fn from(pair: Pair) -> Self {
2,674✔
46
        SteelVal::Pair(Gc::new(pair))
2,674✔
47
    }
48
}
49

50
impl std::fmt::Debug for Pair {
51
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
52
        write!(f, "({} . {})", &self.car, &self.cdr)
×
53
    }
54
}
55

56
#[cfg(feature = "without-drop-protection")]
57
type DropHandlerChoice = im_lists::handler::DefaultDropHandler;
58
#[cfg(not(feature = "without-drop-protection"))]
59
type DropHandlerChoice = list_drop_handler::ListDropHandler;
60

61
thread_local! {
62
    pub static DEPTH: Cell<usize> = const { Cell::new(0) };
63
}
64

65
pub struct GcPointerType;
66

67
impl PointerFamily for GcPointerType {
68
    type Pointer<T: 'static> = Gc<T>;
69

70
    fn new<T: 'static>(value: T) -> Self::Pointer<T> {
13,708,016✔
71
        Gc::new(value)
27,416,032✔
72
    }
73

74
    fn strong_count<T: 'static>(this: &Self::Pointer<T>) -> usize {
360,070✔
75
        Gc::strong_count(this)
720,140✔
76
    }
77

78
    fn try_unwrap<T: 'static>(this: Self::Pointer<T>) -> Option<T> {
8,720,168✔
79
        Gc::try_unwrap(this).ok()
26,160,504✔
80
    }
81

82
    fn get_mut<T: 'static>(this: &mut Self::Pointer<T>) -> Option<&mut T> {
23,459,105✔
83
        Gc::get_mut(this)
46,918,210✔
84
    }
85

86
    fn ptr_eq<T: 'static>(this: &Self::Pointer<T>, other: &Self::Pointer<T>) -> bool {
8,851,646✔
87
        Gc::ptr_eq(this, other)
26,554,938✔
88
    }
89

90
    fn make_mut<T: Clone + 'static>(ptr: &mut Self::Pointer<T>) -> &mut T {
10,526,617✔
91
        Gc::make_mut(ptr)
10,526,617✔
92
    }
93

94
    fn clone<T: 'static>(ptr: &Self::Pointer<T>) -> Self::Pointer<T> {
2,435,409✔
95
        Gc::clone(ptr)
4,870,818✔
96
    }
97

98
    fn as_ptr<T: 'static>(this: &Self::Pointer<T>) -> *const T {
6,007,709✔
99
        Gc::as_ptr(this)
12,015,418✔
100
    }
101

102
    fn into_raw<T: 'static>(this: Self::Pointer<T>) -> *const T {
×
103
        Gc::into_raw(this)
×
104
    }
105

106
    unsafe fn from_raw<T: 'static>(this: *const T) -> Self::Pointer<T> {
64,348✔
107
        Gc::from_raw(this)
128,696✔
108
    }
109
}
110

111
#[cfg(not(feature = "without-drop-protection"))]
112
mod list_drop_handler {
113

114
    use std::collections::VecDeque;
115

116
    use super::*;
117

118
    pub struct ListDropHandler;
119

120
    use crate::rvals::cycles::{drop_impls::DROP_BUFFER, IterativeDropHandler};
121

122
    impl DropHandler<im_lists::list::GenericList<SteelVal, PointerType, 4, 2, Self>>
123
        for ListDropHandler
124
    {
125
        #[inline(always)]
126
        fn drop_handler(obj: &mut im_lists::list::GenericList<SteelVal, PointerType, 4, 2, Self>) {
74,792,639✔
127
            if obj.is_empty() {
149,585,278✔
128
                return;
12,395,441✔
129
            }
130

131
            if obj.strong_count() == 1 {
62,397,198✔
132
                if DROP_BUFFER
5,370,678✔
133
                    .try_with(|drop_buffer| {
10,741,373✔
134
                        if let Ok(mut drop_buffer) = drop_buffer.try_borrow_mut() {
10,726,371✔
135
                            let taken = std::mem::take(obj);
16,067,028✔
136

137
                            for value in taken.draining_iterator() {
28,950,028✔
138
                                match &value {
18,238,676✔
139
                                    SteelVal::BoolV(_)
×
140
                                    | SteelVal::NumV(_)
×
141
                                    | SteelVal::IntV(_)
×
142
                                    | SteelVal::CharV(_)
×
143
                                    | SteelVal::Void
×
144
                                    | SteelVal::StringV(_)
×
145
                                    | SteelVal::FuncV(_)
×
146
                                    | SteelVal::SymbolV(_)
×
147
                                    | SteelVal::FutureFunc(_)
×
148
                                    | SteelVal::FutureV(_)
×
149
                                    | SteelVal::BoxedFunction(_)
×
150
                                    | SteelVal::MutFunc(_)
×
151
                                    | SteelVal::BuiltIn(_)
×
152
                                    | SteelVal::BigNum(_)
×
153
                                    | SteelVal::MutableVector(_) => continue,
14,905,646✔
154
                                    SteelVal::ListV(l) => {
3,098,405✔
155
                                        // println!("Value: {}", l.strong_count());
156
                                        if l.strong_count() == 1 {
3,248,082✔
157
                                            drop_buffer.push_back(value);
299,354✔
158
                                        }
159
                                    }
160
                                    _ => {
234,625✔
161
                                        drop_buffer.push_back(value);
469,250✔
162
                                    }
163
                                }
164
                            }
165

166
                            // println!("{:?}", now.elapsed());
167

168
                            IterativeDropHandler::bfs(&mut drop_buffer);
10,711,352✔
169
                        } else {
170
                            let mut drop_buffer = VecDeque::new();
30,038✔
171

172
                            for value in std::mem::take(obj).draining_iterator() {
60,104✔
173
                                match &value {
15,047✔
174
                                    SteelVal::BoolV(_)
×
175
                                    | SteelVal::NumV(_)
×
176
                                    | SteelVal::IntV(_)
×
177
                                    | SteelVal::CharV(_)
×
178
                                    | SteelVal::Void
×
179
                                    | SteelVal::StringV(_)
×
180
                                    | SteelVal::FuncV(_)
×
181
                                    | SteelVal::SymbolV(_)
×
182
                                    | SteelVal::FutureFunc(_)
×
183
                                    | SteelVal::FutureV(_)
×
184
                                    | SteelVal::BoxedFunction(_)
×
185
                                    | SteelVal::MutFunc(_)
×
186
                                    | SteelVal::BuiltIn(_)
×
187
                                    | SteelVal::BigNum(_)
×
188
                                    | SteelVal::MutableVector(_) => continue,
32✔
189

190
                                    SteelVal::ListV(l) => {
4✔
191
                                        if l.strong_count() == 1 {
8✔
192
                                            drop_buffer.push_back(value);
8✔
193
                                        }
194
                                    }
195

196
                                    _ => {
15,011✔
197
                                        drop_buffer.push_back(value);
30,022✔
198
                                    }
199
                                }
200
                            }
201

202
                            IterativeDropHandler::bfs(&mut drop_buffer);
30,038✔
203
                        }
204
                    })
205
                    .is_err()
206
                {
207
                    let mut drop_buffer = VecDeque::new();
×
208
                    for value in std::mem::take(obj).draining_iterator() {
×
209
                        match &value {
×
210
                            SteelVal::BoolV(_)
×
211
                            | SteelVal::NumV(_)
×
212
                            | SteelVal::IntV(_)
×
213
                            | SteelVal::CharV(_)
×
214
                            | SteelVal::Void
×
215
                            | SteelVal::StringV(_)
×
216
                            | SteelVal::FuncV(_)
×
217
                            | SteelVal::SymbolV(_)
×
218
                            | SteelVal::FutureFunc(_)
×
219
                            | SteelVal::FutureV(_)
×
220
                            | SteelVal::BoxedFunction(_)
×
221
                            | SteelVal::MutFunc(_)
×
222
                            | SteelVal::BuiltIn(_)
×
223
                            | SteelVal::BigNum(_)
×
224
                            | SteelVal::MutableVector(_) => continue,
×
225
                            SteelVal::ListV(l) => {
×
226
                                if l.strong_count() == 1 {
×
227
                                    drop_buffer.push_back(value);
×
228
                                }
229
                            }
230
                            _ => {
×
231
                                drop_buffer.push_back(value);
×
232
                            }
233
                        }
234
                    }
235

236
                    IterativeDropHandler::bfs(&mut drop_buffer);
×
237
                }
238
            }
239
        }
240
    }
241
}
242

243
type PointerType = GcPointerType;
244

245
pub type SteelList<T> = im_lists::list::GenericList<T, PointerType, 4, 2, DefaultDropHandler>;
246

247
pub type List<T> = im_lists::list::GenericList<T, PointerType, 4, 2, DropHandlerChoice>;
248

249
pub(crate) type CellPointer<T> = im_lists::list::RawCell<T, PointerType, 4, 2, DropHandlerChoice>;
250

251
pub type ConsumingIterator<T> =
252
    im_lists::list::ConsumingIter<T, PointerType, 4, 2, DropHandlerChoice>;
253

254
impl<T: FromSteelVal + Clone, D: im_lists::handler::DropHandler<Self>> FromSteelVal
255
    for im_lists::list::GenericList<T, PointerType, 4, 2, D>
256
{
257
    fn from_steelval(val: &SteelVal) -> crate::rvals::Result<Self> {
26✔
258
        if let SteelVal::ListV(l) = val {
52✔
259
            l.iter().map(T::from_steelval).collect()
104✔
260
        } else {
261
            stop!(TypeMismatch => "Unable to convert SteelVal to List, found: {}", val);
×
262
        }
263
    }
264
}
265

266
impl<T: IntoSteelVal + Clone, D: im_lists::handler::DropHandler<Self>> IntoSteelVal
267
    for im_lists::list::GenericList<T, PointerType, 4, 2, D>
268
{
269
    fn into_steelval(self) -> crate::rvals::Result<SteelVal> {
10,953✔
270
        self.into_iter()
21,906✔
271
            .map(|x| x.into_steelval())
12,611✔
272
            .collect::<crate::rvals::Result<List<_>>>()
273
            .map(SteelVal::ListV)
10,953✔
274
    }
275
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc