splitbits!(0b11110000, "aaabbbbb");
to parse a byte into two bit fieldsbitmatch
crate.parse_path
could return a PathBuf
insteadpub 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 astimpl<'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 shownpub 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)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>
anywayerror[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 compilesixup: 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 therelet _ = 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 str
self
reference and the inner lifetime of Foo
Foo
Foo
lifetime to shorter onesFoo
exists?struct
and sees that the lifetime is used in a reference thereself
referenceself
referenceself
referencedrop
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 futureexit
on two different threads is instant UB in C? ^^ exit
implexit
impl, but dropping it under certain circumstances later on. meaning that exit
was usually threadsafe in glibc, but not always)exit
if not everyone takes the same lockexit
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 enoughexit
thread-unsafesys.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 UBexit
from multiple threads UB, over a probably accidental wording issueFile::open
will not cause UB exit
from an atexit
handler UBexit
is not in the otherwise exhaustive list of thread-unsafe functionsFile::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
handlersexit
not in the list of thread-unsafe functions?exit
not being threadsafe is a mistakeexit
not in the list of thread-unsafe functions? exit
is immediately UB, threads shouldn't even come into the equationexit
not being threadsafe is a mistake