Skip to content

Commit

Permalink
Merge pull request #252 from dtolnay/safedisplay
Browse files Browse the repository at this point in the history
Remove unsafe code from AsDisplay
  • Loading branch information
dtolnay authored Sep 2, 2023
2 parents 8245799 + bb49bb3 commit 134695a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 38 deletions.
57 changes: 20 additions & 37 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,38 @@
use std::fmt::{self, Display};
use std::path::{Path, PathBuf};
use std::fmt::Display;
use std::path::{self, Path, PathBuf};

#[doc(hidden)]
pub trait AsDisplay {
type Target: Display + ?Sized;
pub trait AsDisplay<'a> {
type Target: Display;

fn as_display(&self) -> &Self::Target;
fn as_display(&'a self) -> Self::Target;
}

impl<T: Display> AsDisplay for &T {
type Target = T;
impl<'a, T> AsDisplay<'a> for &T
where
T: Display + 'a,
{
type Target = &'a T;

fn as_display(&self) -> &Self::Target {
self
fn as_display(&'a self) -> Self::Target {
*self
}
}

impl AsDisplay for Path {
type Target = PathDisplay;
impl<'a> AsDisplay<'a> for Path {
type Target = path::Display<'a>;

#[inline]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self)
fn as_display(&'a self) -> Self::Target {
self.display()
}
}

impl AsDisplay for PathBuf {
type Target = PathDisplay;
impl<'a> AsDisplay<'a> for PathBuf {
type Target = path::Display<'a>;

#[inline]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self.as_path())
}
}

#[doc(hidden)]
#[repr(transparent)]
pub struct PathDisplay(Path);

impl PathDisplay {
#[inline]
fn new(path: &Path) -> &Self {
// SAFETY: PathDisplay is repr(transparent) so casting pointers between
// it and its payload is safe.
unsafe { &*(path as *const Path as *const Self) }
}
}

impl Display for PathDisplay {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.0.display().fmt(formatter)
fn as_display(&'a self) -> Self::Target {
self.display()
}
}
2 changes: 1 addition & 1 deletion tests/ui/no-display.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ error[E0599]: the method `as_display` exists for reference `&NoDisplay`, but its
|
= note: the following trait bounds were not satisfied:
`NoDisplay: std::fmt::Display`
which is required by `&NoDisplay: AsDisplay`
which is required by `&NoDisplay: AsDisplay<'_>`
note: the trait `std::fmt::Display` must be implemented
--> $RUST/core/src/fmt/mod.rs
|
Expand Down

0 comments on commit 134695a

Please sign in to comment.