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

Add File constructors that return files wrapped with a buffer #130803

Merged
merged 4 commits into from
Sep 25, 2024
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
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/facts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::error::Error;
use std::fmt::Debug;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::io::Write;
use std::path::Path;

use polonius_engine::{AllFacts as PoloniusFacts, Atom};
Expand Down Expand Up @@ -127,7 +127,7 @@ impl<'w> FactWriter<'w> {
T: FactRow,
{
let file = &self.dir.join(file_name);
let mut file = BufWriter::new(File::create(file)?);
let mut file = File::create_buffered(file)?;
for row in rows {
row.write(&mut file, self.location_table)?;
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(file_buffered)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustc_attrs)]
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,7 @@ struct ThinLTOKeysMap {
impl ThinLTOKeysMap {
fn save_to_file(&self, path: &Path) -> io::Result<()> {
use std::io::Write;
let file = File::create(path)?;
let mut writer = io::BufWriter::new(file);
let mut writer = File::create_buffered(path)?;
// The entries are loaded back into a hash map in `load_from_file()`, so
// the order in which we write them to file here does not matter.
for (module, key) in &self.keys {
Expand All @@ -821,8 +820,8 @@ impl ThinLTOKeysMap {
fn load_from_file(path: &Path) -> io::Result<Self> {
use std::io::BufRead;
let mut keys = BTreeMap::default();
let file = File::open(path)?;
for line in io::BufReader::new(file).lines() {
let file = File::open_buffered(path)?;
for line in file.lines() {
let line = line?;
let mut split = line.split(' ');
let module = split.next().unwrap();
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![feature(assert_matches)]
#![feature(exact_size_is_empty)]
#![feature(extern_types)]
#![feature(file_buffered)]
#![feature(hash_raw_entry)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};
use std::{env, iter, mem, str};
use std::{env, io, iter, mem, str};

use cc::windows_registry;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
Expand Down Expand Up @@ -754,7 +753,7 @@ impl<'a> Linker for GccLinker<'a> {
if self.sess.target.is_like_osx {
// Write a plain, newline-separated list of symbols
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;
for sym in symbols {
debug!(" _{sym}");
writeln!(f, "_{sym}")?;
Expand All @@ -765,7 +764,7 @@ impl<'a> Linker for GccLinker<'a> {
}
} else if is_windows {
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;

// .def file similar to MSVC one but without LIBRARY section
// because LD doesn't like when it's empty
Expand All @@ -781,7 +780,7 @@ impl<'a> Linker for GccLinker<'a> {
} else {
// Write an LD version script
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;
writeln!(f, "{{")?;
if !symbols.is_empty() {
writeln!(f, " global:")?;
Expand Down Expand Up @@ -1059,7 +1058,7 @@ impl<'a> Linker for MsvcLinker<'a> {

let path = tmpdir.join("lib.def");
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;

// Start off with the standard module name header and then go
// straight to exports.
Expand Down Expand Up @@ -1648,7 +1647,7 @@ impl<'a> Linker for AixLinker<'a> {
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
let path = tmpdir.join("list.exp");
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;
// FIXME: use llvm-nm to generate export list.
for symbol in symbols {
debug!(" _{symbol}");
Expand Down Expand Up @@ -1961,7 +1960,7 @@ impl<'a> Linker for BpfLinker<'a> {
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
let path = tmpdir.join("symbols");
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;
for sym in symbols {
writeln!(f, "{sym}")?;
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#![feature(cfg_match)]
#![feature(core_intrinsics)]
#![feature(extend_one)]
#![feature(file_buffered)]
#![feature(hash_raw_entry)]
#![feature(macro_metavar_expr)]
#![feature(map_try_insert)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::env::var_os;
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
use std::sync::atomic::{AtomicUsize, Ordering};

Expand Down Expand Up @@ -33,7 +32,7 @@ impl<O: ForestObligation> ObligationForest<O> {

let file_path = dir.as_ref().join(format!("{counter:010}_{description}.gv"));

let mut gv_file = BufWriter::new(File::create(file_path).unwrap());
let mut gv_file = File::create_buffered(file_path).unwrap();

dot::render(&self, &mut gv_file).unwrap();
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_incremental/src/assert_dep_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

use std::env;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::io::Write;

use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::graph::implementation::{Direction, INCOMING, NodeIndex, OUTGOING};
Expand Down Expand Up @@ -245,7 +245,7 @@ fn dump_graph(query: &DepGraphQuery) {
{
// dump a .txt file with just the edges:
let txt_path = format!("{path}.txt");
let mut file = BufWriter::new(File::create(&txt_path).unwrap());
let mut file = File::create_buffered(&txt_path).unwrap();
for (source, target) in &edges {
write!(file, "{source:?} -> {target:?}\n").unwrap();
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_incremental/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![deny(missing_docs)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(file_buffered)]
#![feature(rustdoc_internals)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![feature(decl_macro)]
#![feature(file_buffered)]
#![feature(let_chains)]
#![feature(try_blocks)]
#![warn(unreachable_pub)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
write_deps_to_file(&mut file)?;
}
OutFileName::Real(ref path) => {
let mut file = BufWriter::new(fs::File::create(path)?);
let mut file = fs::File::create_buffered(path)?;
write_deps_to_file(&mut file)?;
}
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_metadata/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
}

pub fn copy_to_stdout(from: &Path) -> io::Result<()> {
let file = fs::File::open(from)?;
let mut reader = io::BufReader::new(file);
let mut reader = fs::File::open_buffered(from)?;
let mut stdout = io::stdout();
io::copy(&mut reader, &mut stdout)?;
Ok(())
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#![feature(decl_macro)]
#![feature(error_iter)]
#![feature(extract_if)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]
#![feature(let_chains)]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#![feature(discriminant_kind)]
#![feature(extern_types)]
#![feature(extract_if)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(iter_from_coroutine)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ pub fn create_dump_file<'tcx>(
)
})?;
}
Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| {
Ok(fs::File::create_buffered(&file_path).map_err(|e| {
io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}"))
})?))
})?)
}

///////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_mir_dataflow/src/framework/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ where
A::Domain: DebugWithContext<A>,
{
use std::fs;
use std::io::{self, Write};
use std::io::Write;

let def_id = body.source.def_id();
let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else {
Expand All @@ -281,8 +281,7 @@ where
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let f = fs::File::create(&path)?;
io::BufWriter::new(f)
fs::File::create_buffered(&path)?
}

None if dump_enabled(tcx, A::NAME, def_id) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_dataflow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
#![feature(file_buffered)]
#![feature(let_chains)]
#![feature(try_blocks)]
#![warn(unreachable_pub)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/dump_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
write_mir_pretty(tcx, None, &mut f)?;
}
OutFileName::Real(path) => {
let mut f = io::BufWriter::new(File::create(&path)?);
let mut f = File::create_buffered(&path)?;
write_mir_pretty(tcx, None, &mut f)?;
if tcx.sess.opts.json_artifact_notifications {
tcx.dcx().emit_artifact_notification(&path, "mir");
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![feature(box_patterns)]
#![feature(const_type_name)]
#![feature(cow_is_borrowed)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(let_chains)]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_monomorphize/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![feature(array_windows)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![warn(unreachable_pub)]
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
use std::cmp;
use std::collections::hash_map::Entry;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::io::Write;
use std::path::{Path, PathBuf};

use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
Expand Down Expand Up @@ -1243,8 +1243,7 @@ fn dump_mono_items_stats<'tcx>(
let ext = format.extension();
let filename = format!("{crate_name}.mono_items.{ext}");
let output_path = output_directory.join(&filename);
let file = File::create(&output_path)?;
let mut file = BufWriter::new(file);
let mut file = File::create_buffered(&output_path)?;

// Gather instantiated mono items grouped by def_id
let mut items_per_def_id: FxIndexMap<_, Vec<_>> = Default::default();
Expand Down
77 changes: 77 additions & 0 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,44 @@ impl File {
OpenOptions::new().read(true).open(path.as_ref())
}

/// Attempts to open a file in read-only mode with buffering.
///
/// See the [`OpenOptions::open`] method, the [`BufReader`][io::BufReader] type,
/// and the [`BufRead`][io::BufRead] trait for more details.
///
/// If you only need to read the entire file contents,
/// consider [`std::fs::read()`][self::read] or
/// [`std::fs::read_to_string()`][self::read_to_string] instead.
///
/// # Errors
///
/// This function will return an error if `path` does not already exist.
/// Other errors may also be returned according to [`OpenOptions::open`].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems incomplete, since it can also return an error from try_new_buffer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, see #131462.

///
/// # Examples
///
/// ```no_run
/// #![feature(file_buffered)]
/// use std::fs::File;
/// use std::io::BufRead;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::open_buffered("foo.txt")?;
/// assert!(f.capacity() > 0);
/// for (line, i) in f.lines().zip(1..) {
/// println!("{i:6}: {}", line?);
/// }
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_buffered", issue = "130804")]
pub fn open_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufReader<File>> {
// Allocate the buffer *first* so we don't affect the filesystem otherwise.
let buffer = io::BufReader::<Self>::try_new_buffer()?;
let file = File::open(path)?;
Ok(io::BufReader::with_buffer(file, buffer))
}

/// Opens a file in write-only mode.
///
/// This function will create a file if it does not exist,
Expand Down Expand Up @@ -404,6 +442,45 @@ impl File {
OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
}

/// Opens a file in write-only mode with buffering.
///
/// This function will create a file if it does not exist,
/// and will truncate it if it does.
///
/// Depending on the platform, this function may fail if the
/// full directory path does not exist.
///
/// See the [`OpenOptions::open`] method and the
/// [`BufWriter`][io::BufWriter] type for more details.
///
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with some given data.
///
/// # Examples
///
/// ```no_run
/// #![feature(file_buffered)]
/// use std::fs::File;
/// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create_buffered("foo.txt")?;
/// assert!(f.capacity() > 0);
/// for i in 0..100 {
/// writeln!(&mut f, "{i}")?;
/// }
/// f.flush()?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "file_buffered", issue = "130804")]
pub fn create_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufWriter<File>> {
// Allocate the buffer *first* so we don't affect the filesystem otherwise.
let buffer = io::BufWriter::<Self>::try_new_buffer()?;
let file = File::create(path)?;
Ok(io::BufWriter::with_buffer(file, buffer))
}

/// Creates a new file in read-write mode; error if the file exists.
///
/// This function will create a file if it does not exist, or return an error if it does. This
Expand Down
Loading
Loading