99// except according to those terms.
1010
1111//! Failure support for libcore
12+ //!
13+ //! The core library cannot define failure, but it does *declare* failure. This
14+ //! means that the functions inside of libcore are allowed to fail, but to be
15+ //! useful an upstream crate must define failure for libcore to use. The current
16+ //! interface for failure is:
17+ //!
18+ //! fn begin_unwind(fmt: &fmt::Arguments, file: &str, line: uint) -> !;
19+ //!
20+ //! This definition allows for failing with any general message, but it does not
21+ //! allow for failing with a `~Any` value. The reason for this is that libcore
22+ //! is not allowed to allocate.
23+ //!
24+ //! This module contains a few other failure functions, but these are just the
25+ //! necessary lang items for the compiler. All failure is funneled through this
26+ //! one function. Currently, the actual symbol is declared in the standard
27+ //! library, but the location of this may change over time.
1228
1329#![ allow( dead_code, missing_doc) ]
1430
1531#[ cfg( not( test) ) ]
1632use str:: raw:: c_str_to_static_slice;
17-
18- // FIXME: Once std::fmt is in libcore, all of these functions should delegate
19- // to a common failure function with this signature:
20- //
21- // extern {
22- // fn rust_unwind(f: &fmt::Arguments, file: &str, line: uint) -> !;
23- // }
24- //
25- // Each of these functions can create a temporary fmt::Arguments
26- // structure to pass to this function.
33+ use fmt;
2734
2835#[ cold] #[ inline( never) ] // this is the slow path, always
2936#[ lang="fail_" ]
@@ -32,24 +39,31 @@ fn fail_(expr: *u8, file: *u8, line: uint) -> ! {
3239 unsafe {
3340 let expr = c_str_to_static_slice ( expr as * i8 ) ;
3441 let file = c_str_to_static_slice ( file as * i8 ) ;
35- begin_unwind ( expr, file, line)
42+ format_args ! ( |args| -> ( ) {
43+ begin_unwind( args, file, line) ;
44+ } , "{}" , expr) ;
45+
46+ loop { }
3647 }
3748}
3849
3950#[ cold]
4051#[ lang="fail_bounds_check" ]
4152#[ cfg( not( test) ) ]
4253fn fail_bounds_check ( file : * u8 , line : uint , index : uint , len : uint ) -> ! {
43- #[ allow( ctypes) ]
44- extern { fn rust_fail_bounds_check ( file : * u8 , line : uint ,
45- index : uint , len : uint , ) -> !; }
46- unsafe { rust_fail_bounds_check ( file, line, index, len) }
54+ let file = unsafe { c_str_to_static_slice ( file as * i8 ) } ;
55+ format_args ! ( |args| -> ( ) {
56+ begin_unwind( args, file, line) ;
57+ } , "index out of bounds: the len is {} but the index is {}" , len, index) ;
58+ loop { }
4759}
4860
4961#[ cold]
50- pub fn begin_unwind ( msg : & str , file : & ' static str , line : uint ) -> ! {
62+ pub fn begin_unwind ( fmt : & fmt:: Arguments , file : & ' static str , line : uint ) -> ! {
63+ // FIXME: this should be a proper lang item, it should not just be some
64+ // undefined symbol sitting in the middle of nowhere.
5165 #[ allow( ctypes) ]
52- extern { fn rust_begin_unwind ( msg : & str , file : & ' static str ,
66+ extern { fn rust_begin_unwind ( fmt : & fmt :: Arguments , file : & ' static str ,
5367 line : uint ) -> !; }
54- unsafe { rust_begin_unwind ( msg , file, line) }
68+ unsafe { rust_begin_unwind ( fmt , file, line) }
5569}
0 commit comments