Skip to content

Commit bf2c75a

Browse files
committed
Rollup merge of rust-lang#22499 - pnkfelix:purge-demo-of-exchange-malloc-and-free, r=steveklabnik
Revise `lang_item` demo to something unrelated to `Box` impl Precursor for landing overloaded-`box`, since that will decouple the `box` syntax from the exchange heap (and should eliminate the use of the two aforementioned lang items). Instead, the new demonstration program shows a definition of the `panic_bounds_check` lang item. (We do not have that many procedural lang-items to choose from, which is a good sign for our efforts to decouple the compiler from the runtime!) ---- Precursor for overloaded-`box` and placement-`in`; see Issue rust-lang#22181.
2 parents fb17900 + 2b7f7f2 commit bf2c75a

File tree

1 file changed

+56
-31
lines changed

1 file changed

+56
-31
lines changed

src/doc/trpl/unsafe.md

+56-31
Original file line numberDiff line numberDiff line change
@@ -649,53 +649,78 @@ it exists. The marker is the attribute `#[lang="..."]` and there are
649649
various different values of `...`, i.e. various different 'lang
650650
items'.
651651

652-
For example, `Box` pointers require two lang items, one for allocation
653-
and one for deallocation. A freestanding program that uses the `Box`
654-
sugar for dynamic allocations via `malloc` and `free`:
652+
For example, there are three lang items related to task panicking:
653+
one, `panic_bounds_check`, is called on panics due to out-of-bounds
654+
array accesses; the second, `panic`, is used by explicit invocations
655+
of `panic!`, and a third, `panic_fmt`, handles unwinding the stack in
656+
the Rust standard library.
657+
658+
A freestanding program that provides its own definition of the
659+
`panic_bounds_check` lang item:
655660

656661
```
657-
#![feature(lang_items, box_syntax, start, no_std)]
662+
#![feature(lang_items, intrinsics, start, no_std)]
658663
#![no_std]
659664
660-
extern crate libc;
661-
662-
extern {
663-
fn abort() -> !;
664-
}
665+
// To be able to print to standard output from this demonstration
666+
// program, we link with `printf` from the C standard library. Note
667+
// that this requires we null-terminate our strings with "\0".
665668
666-
#[lang = "owned_box"]
667-
pub struct Box<T>(*mut T);
669+
mod printf {
670+
#[link(name="c")]
671+
extern { fn printf(f: *const u8, ...); }
668672
669-
#[lang="exchange_malloc"]
670-
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
671-
let p = libc::malloc(size as libc::size_t) as *mut u8;
673+
extern "rust-intrinsic" {
674+
pub fn transmute<T,U>(e: T) -> U;
675+
}
672676
673-
// malloc failed
674-
if p as usize == 0 {
675-
abort();
677+
pub unsafe fn print0(s: &str) {
678+
let (bytes, _len): (*const u8, usize) = transmute(s);
679+
printf(bytes);
676680
}
677681
678-
p
682+
pub unsafe fn print2(s: &str, arg1: u32, arg2: u32) {
683+
let (bytes, _len): (*const u8, usize) = transmute(s);
684+
printf(bytes, arg1, arg2);
685+
}
679686
}
680-
#[lang="exchange_free"]
681-
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
682-
libc::free(ptr as *mut libc::c_void)
687+
688+
#[lang="panic_bounds_check"]
689+
fn panic_bounds_check(_file_line: &(&'static str, usize),
690+
index: usize, len: usize) {
691+
// For simplicity of demonstration, just print message and exit.
692+
extern { fn exit(status: u32) -> !; }
693+
694+
let index = index as u32;
695+
let len = len as u32;
696+
unsafe {
697+
printf::print2("panic_bounds_check index: %d len: %d\n\0", index, len);
698+
699+
// (we pass 0 since this is expected behavior for the demonstration.)
700+
exit(0);
701+
}
683702
}
684703
685704
#[start]
686-
fn main(argc: isize, argv: *const *const u8) -> isize {
687-
let x = box 1;
688-
689-
0
705+
fn main(_argc: isize, _argv: *const *const u8) -> isize {
706+
let a = [100, 200, 300];
707+
unsafe { printf::print0("doing a[4] for a.len() == 3\n\0"); }
708+
a[4];
709+
unsafe { printf::print0("Should not get here.\n\0"); }
710+
return 0;
690711
}
691712
713+
// Again, these functions and traits are used by the compiler, and are
714+
// normally provided by libstd. (The `Sized` and `Copy` lang_items
715+
// require definitions due to the type-parametric code above.)
716+
692717
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
693718
#[lang = "eh_personality"] extern fn eh_personality() {}
694719
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
695-
```
696720
697-
Note the use of `abort`: the `exchange_malloc` lang item is assumed to
698-
return a valid pointer, and so needs to do the check internally.
721+
#[lang="sized"] pub trait Sized {}
722+
#[lang="copy"] pub trait Copy {}
723+
```
699724

700725
Other features provided by lang items include:
701726

@@ -712,6 +737,6 @@ Other features provided by lang items include:
712737
`contravariant_lifetime`, etc.
713738

714739
Lang items are loaded lazily by the compiler; e.g. if one never uses
715-
`Box` then there is no need to define functions for `exchange_malloc`
716-
and `exchange_free`. `rustc` will emit an error when an item is needed
717-
but not found in the current crate or any that it depends on.
740+
array indexing `a[i]` then there is no need to define a function for
741+
`panic_bounds_check`. `rustc` will emit an error when an item is
742+
needed but not found in the current crate or any that it depends on.

0 commit comments

Comments
 (0)