First off, I have no clue what impact this may have or if there would be any ramifications(especially since I don't know a lot of about the internals of rustc), but I had an idea while writing some code for an OS I'm making. My idea is to allow blocks that look something like safe { /* code */ }
inside unsafe blocks(so something like unsafe { /* unsafe code */ safe { /* safe code */ } /* more unsafe code */ }
) as, for example, I was writing a function like this(ignore the contents, it's not super important):
/// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe {
let unitable: &[&str] = &[];
let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize);
/* Safe block start */
for i in 0..(data.num_glyphs as usize) {
let char = (*unistr)[i];
/* Didn't finish writing code here lol */
}
/* Safe block end */
let out = PCScreenFont {
version: data.version,
flags: data.flags,
height: data.height,
width: data.width,
glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]),
unitable
};
Ok(out)
}
}
And I'd like to have the for loop be safe so that I can re-enable some of the compilers checks, however having something like:
/// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe {
let unitable: &[&str] = &[];
let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize);
}
for i in 0..(data.num_glyphs as usize) {
let char = (*unistr)[i];
/* Didn't finish writing code here lol */
}
unsafe {
let out = PCScreenFont {
version: data.version,
flags: data.flags,
height: data.height,
width: data.width,
glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]),
unitable
};
Ok(out)
}
}
seems too obtrusive. Please let me know if I'm missing something, but here's an example code sample with my same example:
/// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe {
let unitable: &[&str] = &[];
let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize);
safe {
for i in 0..(data.num_glyphs as usize) {
let char = (*unistr)[i];
/* Didn't finish writing code here lol */
}
}
let out = PCScreenFont {
version: data.version,
flags: data.flags,
height: data.height,
width: data.width,
glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]),
unitable
};
Ok(out)
}
}
Also, having a safe block like this makes it more obvious that this code is safe code when the surrounding isn't, although I suppose that the version that'd be used right now would make it more explicit that the code at the end of the "safe block" is unsafe again. I figure this would go through the RFC process, but I wanted to gauge interest first.