Skip to content

Commit

Permalink
Move to using an extern type for opaqueness
Browse files Browse the repository at this point in the history
This prevents accidental dereferences and so forth of the Void type, as well as
cleaning up the error message to reference Opaque rather than the more
complicated PhantomData type.
  • Loading branch information
Mark-Simulacrum committed Feb 17, 2020
1 parent 6c45e45 commit 34ef8f5
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 24 deletions.
16 changes: 4 additions & 12 deletions src/libcore/fmt/mod.rs
Expand Up @@ -238,16 +238,8 @@ pub struct Formatter<'a> {
// NB. Argument is essentially an optimized partially applied formatting function,
// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.

struct Void {
_priv: (),
/// Erases all oibits, because `Void` erases the type of the object that
/// will be used to produce formatted output. Since we do not know what
/// oibits the real types have (and they can have any or none), we need to
/// take the most conservative approach and forbid all oibits.
///
/// It was added after #45197 showed that one could share a `!Sync`
/// object across threads by passing it into `format_args!`.
_oibit_remover: PhantomData<*mut dyn Fn()>,
extern "C" {
type Opaque;
}

/// This struct represents the generic "argument" which is taken by the Xprintf
Expand All @@ -259,8 +251,8 @@ struct Void {
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
#[doc(hidden)]
pub struct ArgumentV1<'a> {
value: &'a Void,
formatter: fn(&Void, &mut Formatter<'_>) -> Result,
value: &'a Opaque,
formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
}

impl<'a> ArgumentV1<'a> {
Expand Down
20 changes: 8 additions & 12 deletions src/test/ui/fmt/send-sync.stderr
@@ -1,34 +1,30 @@
error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
--> $DIR/send-sync.rs:8:5
|
LL | fn send<T: Send>(_: T) {}
| ---- ---- required by this bound in `send`
...
LL | send(format_args!("{:?}", c));
| ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
| ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
|
= help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
= note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `core::fmt::Opaque`
= note: required because it appears within the type `&core::fmt::Opaque`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
= note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
= note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `std::fmt::Arguments<'_>`

error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
--> $DIR/send-sync.rs:9:5
|
LL | fn sync<T: Sync>(_: T) {}
| ---- ---- required by this bound in `sync`
...
LL | sync(format_args!("{:?}", c));
| ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
| ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
|
= help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
= note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `core::fmt::Opaque`
= note: required because it appears within the type `&core::fmt::Opaque`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
= note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]`
Expand Down

0 comments on commit 34ef8f5

Please sign in to comment.