Skip to content

Commit

Permalink
NamedTempFile: Fix infinite recursion in trait bounds (#225)
Browse files Browse the repository at this point in the history
Due to bug rust-lang/rust#96634, these generic bounds may cause an
infinite recursion in the compiler, even in unrelated code.

This specializes the `Write for &NamedTempFile<F>` impl on `File`
instead. This keeps the API the same as before the generic parameter `F`
was added, so it shouldn't break any code.
  • Loading branch information
jasonwhite authored Mar 29, 2023
1 parent 7c77c19 commit 8ad7b8c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
15 changes: 3 additions & 12 deletions src/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,10 +918,7 @@ impl<F: Read> Read for NamedTempFile<F> {
}
}

impl<'a, F> Read for &'a NamedTempFile<F>
where
&'a F: Read,
{
impl Read for &NamedTempFile<File> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file().read(buf).with_err_path(|| self.path())
}
Expand All @@ -937,10 +934,7 @@ impl<F: Write> Write for NamedTempFile<F> {
}
}

impl<'a, F> Write for &'a NamedTempFile<F>
where
&'a F: Write,
{
impl Write for &NamedTempFile<File> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file().write(buf).with_err_path(|| self.path())
}
Expand All @@ -956,10 +950,7 @@ impl<F: Seek> Seek for NamedTempFile<F> {
}
}

impl<'a, F> Seek for &'a NamedTempFile<F>
where
&'a F: Seek,
{
impl Seek for &NamedTempFile<File> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.as_file().seek(pos).with_err_path(|| self.path())
}
Expand Down
25 changes: 25 additions & 0 deletions tests/namedtempfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,28 @@ fn test_make_uds_conflict() {
assert!(socket.path().exists());
}
}

// Issue #224.
#[test]
fn test_overly_generic_bounds() {
pub struct Foo<T>(T);

impl<T> Foo<T>
where
T: Sync + Send + 'static,
for<'a> &'a T: Write + Read,
{
pub fn new(foo: T) -> Self {
Self(foo)
}
}

// Don't really need to run this. Only care if it compiles.
if let Ok(file) = File::open("i_do_not_exist") {
let mut f;
let _x = {
f = Foo::new(file);
&mut f
};
}
}

0 comments on commit 8ad7b8c

Please sign in to comment.