-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement a format_args!() macro #9012
Conversation
An example of the syntactic expansion is fn main() {
format_args!(|test| { use_test(test) }, "{}", 2);
} to priv use std::prelude::*;
priv extern mod std;
mod __std_macros {
#[macro_escape];
#[doc(hidden)];
priv use std::prelude::*;
}
fn main() {
{
#[address_insignificant]
pub static __static_fmtstr: [::std::fmt::rt::Piece<'static>, ..1u] =
[::std::fmt::rt::Argument(::std::fmt::rt::Argument{position:
::std::fmt::rt::ArgumentNext,
format:
::std::fmt::rt::FormatSpec{fill:
' ',
align:
::std::fmt::parse::AlignUnknown,
flags:
0u,
precision:
::std::fmt::parse::CountImplied,
width:
::std::fmt::parse::CountImplied,},
method:
None,})];
let __arg0 = &2;
let args: &[::std::fmt::Argument] =
&[::std::fmt::argument(::std::fmt::Default::fmt, __arg0)];
let ret: ::std::fmt::Arguments =
unsafe {
::std::cast::transmute((__static_fmtstr.as_slice(), args))
};
|test| { use_test(test) }(&ret)
};
} |
Changed my mind, instead of calling |
unsafe { write_unsafe(output, args.fmt, args.args) } | ||
} | ||
|
||
/// The `write` function takes an output stream, a precompiled format string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"The write_unsafe
function"?
Ok; looks pretty good, some nits/questions here and there. It'd be good to have negative tests for situations like
Part of #9036?
(Needs a rebase, btw.) |
The compile-fail tests were a good idea, I was able to improve the span of the error message when you didn't supply a function (supplied a string instead). I don't think that this is related to #9036 right now, but that still requires more investigation (will resume once this lands). Hmm, I'm still a little torn on the name for this, so I suppose I'll just leave it as |
(also re-pushed) |
/// which is valid because the compiler performs all necessary validation to | ||
/// ensure that the resulting call to format/write would be safe. | ||
#[doc(hidden)] #[inline] | ||
pub unsafe fn mkarguments<'a>(fmt: &'static [rt::Piece<'static>], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why mkarguments
rather than Arguments::new
?
The purpose of this macro is to further reduce the number of allocations which occur when dealing with formatting strings. This macro will perform all of the static analysis necessary to validate that a format string is safe, and then it will wrap up the "format string" into an opaque struct which can then be passed around. Two safe functions are added (write/format) which take this opaque argument structure, unwrap it, and then call the unsafe version of write/format (in an unsafe block). Other than these two functions, it is not intended for anyone to ever look inside this opaque struct. The macro looks a bit odd, but mostly because of rvalue lifetimes this is the only way for it to be safe that I know of. Example use-cases of this are: * third-party libraries can use the default formatting syntax without any forced allocations * the fail!() macro can avoid allocating the format string * the logging macros can avoid allocation any strings
Thanks again for the feedback! updated again. |
r+, but I wonder if we could just write everything in terms of |
Hmm... that's actually not a bad idea. I will investigate this after landing. It would certainly simplify |
The purpose of this macro is to further reduce the number of allocations which occur when dealing with formatting strings. This macro will perform all of the static analysis necessary to validate that a format string is safe, and then it will wrap up the "format string" into an opaque struct which can then be passed around. Two safe functions are added (write/format) which take this opaque argument structure, unwrap it, and then call the unsafe version of write/format (in an unsafe block). Other than these two functions, it is not intended for anyone to ever look inside this opaque struct. The macro looks a bit odd, but mostly because of rvalue lifetimes this is the only way for it to be safe that I know of. Example use-cases of this are: * third-party libraries can use the default formatting syntax without any forced allocations * the fail!() macro can avoid allocating the format string * the logging macros can avoid allocation any strings I plan on transitioning the standard logging/failing to using these macros soon. This is currently blocking on inner statics being usable in cross-crate situations (still tracking down bugs there), but this will hopefully be coming soon! Additionally, I'd rather settle on a name now than later, so if anyone has a better suggestion other than `format_args`, I'm not attached to the name at all :)
This follows from the discussion in #9012. * All macros are now defined in terms of `format_args!` allowing for removal of a good bit of code in the syntax extension * The syntax extension is now in a more aptly-named file, `format.rs` * Documentation was added for the `format!`-related macros.
The purpose of this macro is to further reduce the number of allocations which
occur when dealing with formatting strings. This macro will perform all of the
static analysis necessary to validate that a format string is safe, and then it
will wrap up the "format string" into an opaque struct which can then be passed
around.
Two safe functions are added (write/format) which take this opaque argument
structure, unwrap it, and then call the unsafe version of write/format (in an
unsafe block). Other than these two functions, it is not intended for anyone to
ever look inside this opaque struct.
The macro looks a bit odd, but mostly because of rvalue lifetimes this is the
only way for it to be safe that I know of.
Example use-cases of this are:
forced allocations
I plan on transitioning the standard logging/failing to using these macros soon. This is currently blocking on inner statics being usable in cross-crate situations (still tracking down bugs there), but this will hopefully be coming soon!
Additionally, I'd rather settle on a name now than later, so if anyone has a better suggestion other than
format_args
, I'm not attached to the name at all :)