






splitbits!(0b11110000, "aaabbbbb"); to parse a byte into two bit fields
bitmatch crate.


























































parse_path could return a PathBuf instead




















pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast>
{
let c = asdsadsa
}
drop


pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> 








-Zpolonius on nightly, I'm just curious







pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> {
let (path, absolute) = if path.starts_with("::") {
(path.strip_prefix("::").unwrap(), true)
} else {
(path, false)
};
let segments: Vec<_> = path
.split("::")
.filter_map(|s| {
if s.is_empty() {
None
} else {
Some(PathSegment(s.alloc_on(self)))
}
})
.collect();
Path { absolute, segments }
}
}Some(PathSegment(s.alloc_on(self)))

pub struct PathSegment<'ast>(pub &'ast str);
pub struct Path<'ast> {
pub absolute: bool,
pub segments: Vec<PathSegment<'ast>>,
}
Does seem it behaves similarly though, it is not an owned type, it just refers to the ast
impl<'gcx, T: Allocatable> ArenaAllocatable<'gcx, AstCtx<'gcx>> for T
where
T: 'gcx,
{
type ReturnType = &'gcx T;
fn alloc_on(self, ctx: &'gcx AstCtx<'gcx>) -> Self::ReturnType {
ctx.arena.alloc(self)
}
}






let _ = ();
_ = ();

dev profile [unoptimized + debuginfo] target(s) in 0.56s
Running target/debug/playground

let _ = ();
_ = (); 






-Zpolonius on nightly, I'm just curious 





















pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> {
to
pub fn parse_path(&self, path: &'_ str) -> Path<'ast> {
error wasn't shown





pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> {
to
pub fn parse_path(&self, path: &'_ str) -> Path<'ast> {
error wasn't shown 'ast anyway. This is where my Rust lifetime knowledge ends, you'll have to ask @Ryozuki or @heinrich5991 (edited)




use std::collections::HashSet;
struct Foo<'a> {
bar: HashSet<&'a str>,
}
impl<'a> Foo<'a> {
fn new() -> Self {
Self {
bar: HashSet::new(),
}
}
fn test(&'a self) -> &'a str {
todo!();
}
}
fn main() {
let foo = Foo::new();
let c = foo.test();
std::mem::drop(foo);
}





self.bar.get("").unwrap() and nothing changed

'ast anyway. This is where my Rust lifetime knowledge ends, you'll have to ask @Ryozuki or @heinrich5991 (edited)







src/alumina-boot/src/compiler.rs:263 (edited)
1
1
error[E0505]: cannot move out of `ast` because it is borrowed
--> src/alumina-boot/src/compiler.rs:263:14
|
102 | .map(|source_file| {
| ------------- borrow of `ast` occurs here
...
112 | Ok((parse_tree, ast.parse_path(&source_file.path)))
| --- borrow occurs due to use in closure
...
263 | drop(ast);
| ^^^
| |
| move out of `ast` occurs here
| borrow later used here
For more information about this error, try `rustc --explain E0505`.
error: could not compile `alumina-boot` (bin "alumina-boot") due to 1 previous error

pub fn parse_path(&self, path: &'_ str) -> Path<'ast> into pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> anyway

error[E0505]: cannot move out of `ast` because it is borrowed
--> src/alumina-boot/src/compiler.rs:263:14
|
102 | .map(|source_file| {
| ------------- borrow of `ast` occurs here
...
112 | Ok((parse_tree, ast.parse_path(&source_file.path)))
| --- borrow occurs due to use in closure
...
263 | drop(ast);
| ^^^
| |
| move out of `ast` occurs here
| borrow later used here
For more information about this error, try `rustc --explain E0505`.
error: could not compile `alumina-boot` (bin "alumina-boot") due to 1 previous error compile function body with
let ast = AstCtx::new();
ast.parse_path(&source_files[0].path);
drop(ast);
todo!();
pub struct AstCtx<'ast> {
pub arena: Bump,
pub counter: Cell<usize>,
types: RefCell<HashSet<TyP<'ast>>>,
strings: RefCell<HashSet<&'ast str>>,
lang_items: RefCell<HashMap<Lang, ItemP<'ast>>>,
local_names: RefCell<HashMap<Id, &'ast str>>,
metadata: RefCell<HashMap<ItemP<'ast>, Metadatum<'ast>>>,
}

pub fn parse_path(&self, path: &'_ str) -> Path<'ast> into pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> anyway pub fn parse_path(&'a self, path: &'b str) -> Path<'ast>


use std::cell::RefCell;
struct Foo<'a> {
bar: RefCell<&'a str>,
}
impl<'a> Foo<'a> {
fn new() -> Self {
Self {
bar: RefCell::new("foo"),
}
}
fn test(&'a self) -> &'a str {
&self.bar.borrow()
}
}
fn main() {
let foo = Foo::new();
let c = foo.test();
std::mem::drop(foo);
}
this code doesn't compile



sixup: couldn't load map maps7/ctf5.map
2024-10-23 21:59:19 I sixup: disabling 0.7 compatibility
2024-10-23 21:59:19 I ddnet-insta: cleaning up database connection ...
2024-10-23 21:59:19 I ddnet-insta: connecting to database ...
DDNet-Server(35680,0x16ff13000) malloc: Corruption of tiny freelist 0x107b05370: size too small (0/7)
DDNet-Server(35680,0x16ff13000) malloc: *** set a breakpoint in malloc_error_break to debug
might also be related to me trying to change my map to one map that has no 0.7 version
ddnet-insta codebase (edited)



sixup: couldn't load map maps7/ctf5.map
2024-10-23 21:59:19 I sixup: disabling 0.7 compatibility
2024-10-23 21:59:19 I ddnet-insta: cleaning up database connection ...
2024-10-23 21:59:19 I ddnet-insta: connecting to database ...
DDNet-Server(35680,0x16ff13000) malloc: Corruption of tiny freelist 0x107b05370: size too small (0/7)
DDNet-Server(35680,0x16ff13000) malloc: *** set a breakpoint in malloc_error_break to debug
might also be related to me trying to change my map to one map that has no 0.7 version
ddnet-insta codebase (edited)










pub struct AstCtx<'ast> {
pub arena: Bump,
pub counter: Cell<usize>,
types: RefCell<HashSet<TyP<'ast>>>,
strings: RefCell<HashSet<&'ast str>>,
lang_items: RefCell<HashMap<Lang, ItemP<'ast>>>,
local_names: RefCell<HashMap<Id, &'ast str>>,
metadata: RefCell<HashMap<ItemP<'ast>, Metadatum<'ast>>>,
} 




void CSnapshotStorage::PurgeAll()
{
while(m_pFirst)
{
CHolder *pNext = m_pFirst->m_pNext;
free(m_pFirst->m_pSnap);
free(m_pFirst->m_pAltSnap);
free(m_pFirst);
m_pFirst = pNext;
}
m_pLast = nullptr;
}
does m_pFirst also need to be reset to null after the loop?=================================================================
==43980==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000018208 at pc 0x0001057de03c bp 0x00016b373320 sp 0x00016b373318
READ of size 8 at 0x606000018208 thread T0
#0 0x1057de038 in CSnapshotStorage::PurgeAll() snapshot.cpp:624
#1 0x104b3e03c in CServer::CClient::Reset() server.cpp:214
#2 0x104badcc0 in CServer::Run() server.cpp:2897
#3 0x104ad90e4 in main main.cpp:198
#4 0x196a68270 (<unknown module>)
0x606000018208 is located 8 bytes inside of 56-byte region [0x606000018200,0x606000018238)
freed by thread T0 here:
#0 0x10735cd40 in free+0x98 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54d40)
#1 0x1057de28c in CSnapshotStorage::PurgeAll() snapshot.cpp:627
#2 0x104beff24 in CSnapshotStorage::~CSnapshotStorage() snapshot.h:137
#3 0x104befeac in CSnapshotStorage::~CSnapshotStorage() snapshot.h:137
#4 0x104befe34 in CServer::CClient::~CClient() server.h:109
#5 0x104b42ff4 in CServer::CClient::~CClient() server.h:109
#6 0x104b51690 in CServer::gCTFState(int) const server.cpp:670
#7 0x104e9b4e8 in CGameContext::OnClientDataPersist(int, void*) gamecontext.cpp:1681
#8 0x104bace14 in CServer::Run() server.cpp:2878
#9 0x104ad90e4 in main main.cpp:198
#10 0x196a68270 (<unknown module>)
previously allocated by thread T0 here:
#0 0x10735cc04 in malloc+0x94 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54c04)
#1 0x1057dea3c in CSnapshotStorage::Add(int, long long, unsigned long, void const*, unsigned long, void const*) snapshot.cpp:665
#2 0x104b5b630 in CServer::DoSnapshot() server.cpp:956
#3 0x104bb1bcc in CServer::Run() server.cpp:2989
#4 0x104ad90e4 in main main.cpp:198
#5 0x196a68270 (<unknown module>)
SUMMARY: AddressSanitizer: heap-use-after-free snapshot.cpp:624 in CSnapshotStorage::PurgeAll()
...
...
==43980==ABORTING




drop doesn't get rid of the variable, just of its value. the type is still there

let _ = a; is a no-op, it doesn't move out of a


use std::collections::HashSet;
struct Foo<'a> {
bar: HashSet<&'a str>,
}
impl<'a> Foo<'a> {
fn new() -> Self {
Self {
bar: HashSet::new(),
}
}
fn test(&'a self) -> &'a str {
todo!();
}
}
fn main() {
let foo = Foo::new();
let c = foo.test();
std::mem::drop(foo);
} 'a from self

todo!() is irrelevant

'a from self 'a changes things there?

pub fn parse_path(&self, path: &'_ str) -> Path<'ast> into pub fn parse_path(&'ast self, path: &'_ str) -> Path<'ast> anyway 







'a changes things there? fn test<'a>(self: &'a Foo<'a>) -> &'a str;
// vs
fn test<'a, 'b>(self: &'b Foo<'a>) -> &'a strself reference and the inner lifetime of FooFoo

Foo lifetime to shorter ones
Foo exists?
struct and sees that the lifetime is used in a reference thereself referenceself reference


self reference












drop doesn't get rid of the variable, just of its value. the type is still there drop



























exit thread-safe? ^^

exit thread-safe? ^^ 

exit thread-safe? ^^ 



exit on two different threads is instant UB in C? ^^


exit on two different threads is instant UB in C? ^^ 
exit will likely become threadsafe in the future


exit on two different threads is instant UB in C? ^^ 

exit impl



exit impl, but dropping it under certain circumstances later on. meaning that exit was usually threadsafe in glibc, but not always)





1



exit if not everyone takes the same lock

exit if not everyone takes the same lock 
sys.exit concurrently with a rust library calling std::process::exit should ideally not be UBstd::env::set_var isn't enough





















exit thread-unsafe

sys.exit concurrently with a rust library calling std::process::exit should ideally not be UB 

std::process::exit will just be hiding the fact that it is indeed very much UB when called at the same time through ffi e.g.


exit thread-unsafe 
File::open will not cause UB

exit from multiple threads UB, over a probably accidental wording issue

File::open will not cause UB 
exit from an atexit handler UBexit is not in the otherwise exhaustive list of thread-unsafe functions



File::open will not cause UB open(2) will behave a certain way, rust relies on that promise which is "correct". The C standard and POSIX never made the promise that exit(3) is thread-safe, marking it "safe" is in"correct"


atexit handlers

exit not in the list of thread-unsafe functions?

exit not being threadsafe is a mistake








exit not in the list of thread-unsafe functions? exit is immediately UB, threads shouldn't even come into the equation


exit not being threadsafe is a mistake 













