Skip to content
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

Cleanup formatting code #67795

Merged
merged 4 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 34 additions & 41 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::mem;
use crate::num::flt2dec;
use crate::ops::Deref;
use crate::result;
use crate::slice;
use crate::str;

mod builders;
Expand Down Expand Up @@ -234,8 +233,6 @@ pub struct Formatter<'a> {
precision: Option<usize>,

buf: &'a mut (dyn Write + 'a),
curarg: slice::Iter<'a, ArgumentV1<'a>>,
args: &'a [ArgumentV1<'a>],
}

// NB. Argument is essentially an optimized partially applied formatting function,
Expand Down Expand Up @@ -1043,8 +1040,6 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
buf: output,
align: rt::v1::Alignment::Unknown,
fill: ' ',
args: args.args,
curarg: args.args.iter(),
};

let mut idx = 0;
Expand All @@ -1063,7 +1058,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
// a string piece.
for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
formatter.buf.write_str(*piece)?;
formatter.run(arg)?;
run(&mut formatter, arg, &args.args)?;
idx += 1;
}
}
Expand All @@ -1077,6 +1072,39 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
Ok(())
}

fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
fmt.fill = arg.format.fill;
fmt.align = arg.format.align;
fmt.flags = arg.format.flags;
fmt.width = getcount(args, &arg.format.width);
fmt.precision = getcount(args, &arg.format.precision);

// Extract the correct argument
let value = {
#[cfg(bootstrap)]
{
match arg.position {
rt::v1::Position::At(i) => args[i],
}
}
#[cfg(not(bootstrap))]
{
args[arg.position]
}
};

// Then actually do some printing
(value.formatter)(value.value, fmt)
}

fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
match *cnt {
rt::v1::Count::Is(n) => Some(n),
rt::v1::Count::Implied => None,
rt::v1::Count::Param(i) => args[i].as_usize(),
}
}

/// Padding after the end of something. Returned by `Formatter::padding`.
#[must_use = "don't forget to write the post padding"]
struct PostPadding {
Expand Down Expand Up @@ -1114,41 +1142,6 @@ impl<'a> Formatter<'a> {
align: self.align,
width: self.width,
precision: self.precision,

// These only exist in the struct for the `run` method,
// which won’t be used together with this method.
curarg: self.curarg.clone(),
args: self.args,
}
}

// First up is the collection of functions used to execute a format string
// at runtime. This consumes all of the compile-time statics generated by
// the format! syntax extension.
fn run(&mut self, arg: &rt::v1::Argument) -> Result {
// Fill in the format parameters into the formatter
self.fill = arg.format.fill;
self.align = arg.format.align;
self.flags = arg.format.flags;
self.width = self.getcount(&arg.format.width);
self.precision = self.getcount(&arg.format.precision);

// Extract the correct argument
let value = match arg.position {
rt::v1::Position::Next => *self.curarg.next().unwrap(),
rt::v1::Position::At(i) => self.args[i],
};

// Then actually do some printing
(value.formatter)(value.value, self)
}

fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
match *cnt {
rt::v1::Count::Is(n) => Some(n),
rt::v1::Count::Implied => None,
rt::v1::Count::Param(i) => self.args[i].as_usize(),
rt::v1::Count::NextParam => self.curarg.next()?.as_usize(),
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/libcore/fmt/rt/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

#[derive(Copy, Clone)]
pub struct Argument {
#[cfg(bootstrap)]
pub position: Position,
#[cfg(not(bootstrap))]
pub position: usize,
pub format: FormatSpec,
}

Expand Down Expand Up @@ -37,12 +40,11 @@ pub enum Alignment {
pub enum Count {
Is(usize),
Param(usize),
NextParam,
Implied,
}

#[cfg(bootstrap)]
#[derive(Copy, Clone)]
pub enum Position {
Next,
At(usize),
}
13 changes: 1 addition & 12 deletions src/librustc_builtin_macros/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,17 +590,6 @@ impl<'a, 'b> Context<'a, 'b> {
parse::NextArgument(ref arg) => {
// Build the position
let pos = {
let pos = |c, arg| {
let mut path = Context::rtpath(self.ecx, "Position");
path.push(self.ecx.ident_of(c, sp));
match arg {
Some(i) => {
let arg = self.ecx.expr_usize(sp, i);
self.ecx.expr_call_global(sp, path, vec![arg])
}
None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
}
};
match arg.position {
parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => {
// Map to index in final generated argument array
Expand All @@ -615,7 +604,7 @@ impl<'a, 'b> Context<'a, 'b> {
arg_idx
}
};
pos("At", Some(arg_idx))
self.ecx.expr_usize(sp, arg_idx)
}

// should never be the case, because names are already
Expand Down
15 changes: 7 additions & 8 deletions src/test/ui/async-await/async-fn-nonsend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// edition:2018
// compile-flags: --crate-type lib

use std::{
cell::RefCell,
fmt::Debug,
rc::Rc,
};
use std::{cell::RefCell, fmt::Debug, rc::Rc};

fn non_sync() -> impl Debug { RefCell::new(()) }
fn non_sync() -> impl Debug {
RefCell::new(())
}

fn non_send() -> impl Debug { Rc::new(()) }
fn non_send() -> impl Debug {
Rc::new(())
}

fn take_ref<T>(_: &T) {}

Expand Down Expand Up @@ -53,5 +53,4 @@ pub fn pass_assert() {
//~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_method_call());
//~^ ERROR future cannot be sent between threads safely
//~^^ ERROR future cannot be sent between threads safely
}
24 changes: 1 addition & 23 deletions src/test/ui/async-await/async-fn-nonsend.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,5 @@ LL | }
LL | }
| - `f` is later dropped here

error: future cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:54:5
|
LL | fn assert_send(_: impl Send) {}
| ----------- ---- required by this bound in `assert_send`
...
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
= help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:43:9
|
LL | let f: &mut std::fmt::Formatter = panic!();
| - has type `&mut std::fmt::Formatter<'_>`
LL | if non_sync().fmt(f).unwrap() == () {
LL | fut().await;
| ^^^^^^^^^^^ await occurs here, with `f` maybe used later
LL | }
LL | }
| - `f` is later dropped here

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors