Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-09-26 05:23:15 +00:00
commit 51087d2247
917 changed files with 22996 additions and 25543 deletions

View file

@ -524,7 +524,7 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "clippy"
version = "0.1.82"
version = "0.1.83"
dependencies = [
"anstream",
"cargo_metadata 0.18.1",
@ -547,13 +547,13 @@ dependencies = [
"termize",
"tokio",
"toml 0.7.8",
"ui_test 0.25.0",
"ui_test",
"walkdir",
]
[[package]]
name = "clippy_config"
version = "0.1.82"
version = "0.1.83"
dependencies = [
"itertools",
"serde",
@ -576,7 +576,7 @@ dependencies = [
[[package]]
name = "clippy_lints"
version = "0.1.82"
version = "0.1.83"
dependencies = [
"arrayvec",
"cargo_metadata 0.18.1",
@ -600,7 +600,7 @@ dependencies = [
[[package]]
name = "clippy_utils"
version = "0.1.82"
version = "0.1.83"
dependencies = [
"arrayvec",
"clippy_config",
@ -902,7 +902,7 @@ dependencies = [
[[package]]
name = "declare_clippy_lint"
version = "0.1.82"
version = "0.1.83"
dependencies = [
"itertools",
"quote",
@ -2269,7 +2269,7 @@ dependencies = [
"rustc_version",
"smallvec",
"tempfile",
"ui_test 0.26.5",
"ui_test",
"windows-sys 0.52.0",
]
@ -5485,33 +5485,6 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
[[package]]
name = "ui_test"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e4f339f62edc873975c47115f9e71c5454ddaa37c1142b42fc0b2672c8dacb"
dependencies = [
"annotate-snippets 0.11.4",
"anyhow",
"bstr",
"cargo-platform",
"cargo_metadata 0.18.1",
"color-eyre",
"colored",
"comma",
"crossbeam-channel",
"indicatif",
"lazy_static",
"levenshtein",
"prettydiff",
"regex",
"rustc_version",
"rustfix",
"serde",
"serde_json",
"spanned",
]
[[package]]
name = "ui_test"
version = "0.26.5"

View file

@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token};
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
use rustc_session::Session;
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_span::Span;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use rustc_target::spec::abi;
use thin_vec::ThinVec;
@ -483,6 +483,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
maybe_stage_features(sess, features, krate);
check_incompatible_features(sess, features);
check_new_solver_banned_features(sess, features);
let mut visitor = PostExpansionVisitor { sess, features };
let spans = sess.psess.gated_spans.spans.borrow();
@ -662,3 +664,22 @@ fn check_incompatible_features(sess: &Session, features: &Features) {
}
}
}
fn check_new_solver_banned_features(sess: &Session, features: &Features) {
if !sess.opts.unstable_opts.next_solver.is_some_and(|n| n.globally) {
return;
}
// Ban GCE with the new solver, because it does not implement GCE correctly.
if let Some(&(_, gce_span, _)) = features
.declared_lang_features
.iter()
.find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
{
sess.dcx().emit_err(errors::IncompatibleFeatures {
spans: vec![gce_span],
f1: Symbol::intern("-Znext-solver=globally"),
f2: sym::generic_const_exprs,
});
}
}

View file

@ -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};
@ -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)?;
}

View file

@ -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)]

View file

@ -34,7 +34,22 @@ pub(crate) fn unsized_info<'tcx>(
let old_info =
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
if data_a.principal_def_id() == data_b.principal_def_id() {
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
// Codegen takes advantage of the additional assumption, where if the
// principal trait def id of what's being casted doesn't change,
// then we don't need to adjust the vtable at all. This
// corresponds to the fact that `dyn Tr<A>: Unsize<dyn Tr<B>>`
// requires that `A = B`; we don't allow *upcasting* objects
// between the same trait with different args. If we, for
// some reason, were to relax the `Unsize` trait, it could become
// unsound, so let's assert here that the trait refs are *equal*.
//
// We can use `assert_eq` because the binders should have been anonymized,
// and because higher-ranked equality now requires the binders are equal.
debug_assert_eq!(
data_a.principal(),
data_b.principal(),
"NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"
);
return old_info;
}

View file

@ -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 {
@ -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();

View file

@ -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)]

View file

@ -1087,16 +1087,17 @@ fn link_natively(
let strip = sess.opts.cg.strip;
if sess.target.is_like_osx {
let stripcmd = "/usr/bin/strip";
match (strip, crate_type) {
(Strip::Debuginfo, _) => {
strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-S"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S"))
}
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-x"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x"))
}
(Strip::Symbols, _) => {
strip_symbols_with_external_utility(sess, "strip", out_filename, None)
strip_symbols_with_external_utility(sess, stripcmd, out_filename, None)
}
(Strip::None, _) => {}
}

View file

@ -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};
@ -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}")?;
@ -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
@ -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:")?;
@ -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.
@ -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}");
@ -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}")?;
}

View file

@ -37,6 +37,7 @@ use crate::back::write::{
submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
};
use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
use crate::meth::load_vtable;
use crate::mir::operand::OperandValue;
use crate::mir::place::PlaceRef;
use crate::traits::*;
@ -124,8 +125,28 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let old_info =
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
if data_a.principal_def_id() == data_b.principal_def_id() {
// A NOP cast that doesn't actually change anything, should be allowed even with
// invalid vtables.
// Codegen takes advantage of the additional assumption, where if the
// principal trait def id of what's being casted doesn't change,
// then we don't need to adjust the vtable at all. This
// corresponds to the fact that `dyn Tr<A>: Unsize<dyn Tr<B>>`
// requires that `A = B`; we don't allow *upcasting* objects
// between the same trait with different args. If we, for
// some reason, were to relax the `Unsize` trait, it could become
// unsound, so let's assert here that the trait refs are *equal*.
//
// We can use `assert_eq` because the binders should have been anonymized,
// and because higher-ranked equality now requires the binders are equal.
debug_assert_eq!(
data_a.principal(),
data_b.principal(),
"NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"
);
// A NOP cast that doesn't actually change anything, let's avoid any
// unnecessary work. This relies on the assumption that if the principal
// traits are equal, then the associated type bounds (`dyn Trait<Assoc=T>`)
// are also equal, which is ensured by the fact that normalization is
// a function and we do not allow overlapping impls.
return old_info;
}
@ -135,14 +156,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
if let Some(entry_idx) = vptr_entry_idx {
let ptr_size = bx.data_layout().pointer_size;
let ptr_align = bx.data_layout().pointer_align.abi;
let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes();
let gep = bx.inbounds_ptradd(old_info, bx.const_usize(vtable_byte_offset));
let new_vptr = bx.load(bx.type_ptr(), gep, ptr_align);
bx.nonnull_metadata(new_vptr);
// VTable loads are invariant.
bx.set_invariant_load(new_vptr);
new_vptr
load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true)
} else {
old_info
}

View file

@ -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)]

View file

@ -28,27 +28,9 @@ impl<'a, 'tcx> VirtualIndex {
let llty = bx.fn_ptr_backend_type(fn_abi);
let ptr_size = bx.data_layout().pointer_size;
let ptr_align = bx.data_layout().pointer_align.abi;
let vtable_byte_offset = self.0 * ptr_size.bytes();
if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
&& bx.cx().sess().lto() == Lto::Fat
{
let typeid = bx
.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty)))
.unwrap();
let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
func
} else {
let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
let ptr = bx.load(llty, gep, ptr_align);
// VTable loads are invariant.
bx.set_invariant_load(ptr);
if nonnull {
bx.nonnull_metadata(ptr);
}
ptr
}
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
}
pub(crate) fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>(
@ -75,31 +57,27 @@ impl<'a, 'tcx> VirtualIndex {
self,
bx: &mut Bx,
llvtable: Bx::Value,
ty: Ty<'tcx>,
) -> Bx::Value {
// Load the data pointer from the object.
debug!("get_int({:?}, {:?})", llvtable, self);
let llty = bx.type_isize();
let ptr_size = bx.data_layout().pointer_size;
let ptr_align = bx.data_layout().pointer_align.abi;
let vtable_byte_offset = self.0 * ptr_size.bytes();
let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
let ptr = bx.load(llty, gep, ptr_align);
// VTable loads are invariant.
bx.set_invariant_load(ptr);
ptr
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false)
}
}
/// This takes a valid `self` receiver type and extracts the principal trait
/// ref of the type.
fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> {
/// ref of the type. Return `None` if there is no principal trait.
fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
for arg in ty.peel_refs().walk() {
if let GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Dynamic(data, _, _) = ty.kind()
{
return data.principal().expect("expected principal trait object");
return data.principal();
}
}
@ -138,3 +116,36 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
vtable
}
/// Call this function whenever you need to load a vtable.
pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
llvtable: Bx::Value,
llty: Bx::Type,
vtable_byte_offset: u64,
ty: Ty<'tcx>,
nonnull: bool,
) -> Bx::Value {
let ptr_align = bx.data_layout().pointer_align.abi;
if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
&& bx.cx().sess().lto() == Lto::Fat
{
if let Some(trait_ref) = dyn_trait_in_self(ty) {
let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap();
let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
return func;
} else if nonnull {
bug!("load nonnull value from a vtable without a principal trait")
}
}
let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
let ptr = bx.load(llty, gep, ptr_align);
// VTable loads are invariant.
bx.set_invariant_load(ptr);
if nonnull {
bx.nonnull_metadata(ptr);
}
ptr
}

View file

@ -1,4 +1,5 @@
use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::ops::Range;
use rustc_data_structures::fx::FxHashMap;
@ -14,7 +15,7 @@ use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
use super::operand::{OperandRef, OperandValue};
use super::place::{PlaceRef, PlaceValue};
use super::{FunctionCx, LocalRef};
use super::{FunctionCx, LocalRef, PerLocalVarDebugInfoIndexVec};
use crate::traits::*;
pub struct FunctionDebugContext<'tcx, S, L> {
@ -48,6 +49,17 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
}
/// Information needed to emit a constant.
pub struct ConstDebugInfo<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
pub name: String,
pub source_info: mir::SourceInfo,
pub operand: OperandRef<'tcx, Bx::Value>,
pub dbg_var: Bx::DIVariable,
pub dbg_loc: Bx::DILocation,
pub fragment: Option<Range<Size>>,
pub _phantom: PhantomData<&'a ()>,
}
#[derive(Clone, Copy, Debug)]
pub struct DebugScope<S, L> {
pub dbg_scope: S,
@ -427,11 +439,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
pub(crate) fn debug_introduce_locals(&self, bx: &mut Bx) {
pub(crate) fn debug_introduce_locals(
&self,
bx: &mut Bx,
consts: Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
) {
if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
for local in self.locals.indices() {
self.debug_introduce_local(bx, local);
}
for ConstDebugInfo { name, source_info, operand, dbg_var, dbg_loc, fragment, .. } in
consts.into_iter()
{
self.set_debug_loc(bx, source_info);
let base = FunctionCx::spill_operand_to_stack(operand, Some(name), bx);
bx.clear_dbg_loc();
bx.dbg_var_addr(dbg_var, dbg_loc, base.val.llval, Size::ZERO, &[], fragment);
}
}
}
@ -439,7 +465,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub(crate) fn compute_per_local_var_debug_info(
&self,
bx: &mut Bx,
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
) -> Option<(
PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>,
Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
)> {
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
let target_is_msvc = self.cx.sess().target.is_like_msvc;
@ -449,6 +478,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
let mut constants = vec![];
let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default();
for var in &self.mir.var_debug_info {
let dbg_scope_and_span = if full_debug_info {
@ -545,23 +575,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
let operand = self.eval_mir_constant_to_operand(bx, &c);
self.set_debug_loc(bx, var.source_info);
let base =
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
bx.clear_dbg_loc();
bx.dbg_var_addr(
constants.push(ConstDebugInfo {
name: var.name.to_string(),
source_info: var.source_info,
operand,
dbg_var,
dbg_loc,
base.val.llval,
Size::ZERO,
&[],
fragment,
);
_phantom: PhantomData,
});
}
}
}
}
Some(per_local)
Some((per_local, constants))
}
}

View file

@ -126,7 +126,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
sym::vtable_align => ty::COMMON_VTABLE_ENTRIES_ALIGN,
_ => bug!(),
};
let value = meth::VirtualIndex::from_index(idx).get_usize(bx, vtable);
let value = meth::VirtualIndex::from_index(idx).get_usize(bx, vtable, callee_ty);
match name {
// Size is always <= isize::MAX.
sym::vtable_size => {

View file

@ -41,6 +41,9 @@ enum CachedLlbb<T> {
Skip,
}
type PerLocalVarDebugInfoIndexVec<'tcx, V> =
IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, V>>>;
/// Master context for codegenning from MIR.
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
instance: Instance<'tcx>,
@ -107,8 +110,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// All `VarDebugInfo` from the MIR body, partitioned by `Local`.
/// This is `None` if no variable debuginfo/names are needed.
per_local_var_debug_info:
Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>>,
per_local_var_debug_info: Option<PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>>,
/// Caller location propagated if this function has `#[track_caller]`.
caller_location: Option<OperandRef<'tcx, Bx::Value>>,
@ -216,7 +218,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// monomorphization, and if there is an error during collection then codegen never starts -- so
// we don't have to do it again.
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
let (per_local_var_debug_info, consts_debug_info) =
fx.compute_per_local_var_debug_info(&mut start_bx).unzip();
fx.per_local_var_debug_info = per_local_var_debug_info;
let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance);
let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order);
@ -268,7 +272,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx.initialize_locals(local_values);
// Apply debuginfo to the newly allocated locals.
fx.debug_introduce_locals(&mut start_bx);
fx.debug_introduce_locals(&mut start_bx, consts_debug_info.unwrap_or_default());
// If the backend supports coverage, and coverage is enabled for this function,
// do any necessary start-of-function codegen (e.g. locals for MC/DC bitmaps).

View file

@ -28,9 +28,9 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// Load size/align from vtable.
let vtable = info.unwrap();
let size = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE)
.get_usize(bx, vtable);
.get_usize(bx, vtable, t);
let align = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN)
.get_usize(bx, vtable);
.get_usize(bx, vtable, t);
// Size is always <= isize::MAX.
let size_bound = bx.data_layout().ptr_sized_integer().signed_max() as u128;

View file

@ -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)]

View file

@ -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};
@ -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();
}

View file

@ -1,8 +1,9 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::fold::shift_vars;
use rustc_middle::ty::{
self, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
self, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
@ -42,14 +43,18 @@ fn associated_type_bounds<'tcx>(
let trait_def_id = tcx.local_parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
match pred.kind().skip_binder() {
ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty,
ty::ClauseKind::Projection(proj) => proj.projection_term.self_ty() == item_ty,
ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty,
_ => false,
}
});
let item_trait_ref = ty::TraitRef::identity(tcx, tcx.parent(assoc_item_def_id.to_def_id()));
let bounds_from_parent =
trait_predicates.predicates.iter().copied().filter_map(|(clause, span)| {
remap_gat_vars_and_recurse_into_nested_projections(
tcx,
filter,
item_trait_ref,
assoc_item_def_id,
span,
clause,
)
});
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses(tcx).chain(bounds_from_parent));
debug!(
@ -63,6 +68,226 @@ fn associated_type_bounds<'tcx>(
all_bounds
}
/// The code below is quite involved, so let me explain.
///
/// We loop here, because we also want to collect vars for nested associated items as
/// well. For example, given a clause like `Self::A::B`, we want to add that to the
/// item bounds for `A`, so that we may use that bound in the case that `Self::A::B` is
/// rigid.
///
/// Secondly, regarding bound vars, when we see a where clause that mentions a GAT
/// like `for<'a, ...> Self::Assoc<'a, ...>: Bound<'b, ...>`, we want to turn that into
/// an item bound on the GAT, where all of the GAT args are substituted with the GAT's
/// param regions, and then keep all of the other late-bound vars in the bound around.
/// We need to "compress" the binder so that it doesn't mention any of those vars that
/// were mapped to params.
fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
tcx: TyCtxt<'tcx>,
filter: PredicateFilter,
item_trait_ref: ty::TraitRef<'tcx>,
assoc_item_def_id: LocalDefId,
span: Span,
clause: ty::Clause<'tcx>,
) -> Option<(ty::Clause<'tcx>, Span)> {
let mut clause_ty = match clause.kind().skip_binder() {
ty::ClauseKind::Trait(tr) => tr.self_ty(),
ty::ClauseKind::Projection(proj) => proj.projection_term.self_ty(),
ty::ClauseKind::TypeOutlives(outlives) => outlives.0,
_ => return None,
};
let gat_vars = loop {
if let ty::Alias(ty::Projection, alias_ty) = *clause_ty.kind() {
if alias_ty.trait_ref(tcx) == item_trait_ref
&& alias_ty.def_id == assoc_item_def_id.to_def_id()
{
// We have found the GAT in question...
// Return the vars, since we may need to remap them.
break &alias_ty.args[item_trait_ref.args.len()..];
} else {
// Only collect *self* type bounds if the filter is for self.
match filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
return None;
}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
}
clause_ty = alias_ty.self_ty();
continue;
}
}
return None;
};
// Special-case: No GAT vars, no mapping needed.
if gat_vars.is_empty() {
return Some((clause, span));
}
// First, check that all of the GAT args are substituted with a unique late-bound arg.
// If we find a duplicate, then it can't be mapped to the definition's params.
let mut mapping = FxIndexMap::default();
let generics = tcx.generics_of(assoc_item_def_id);
for (param, var) in std::iter::zip(&generics.own_params, gat_vars) {
let existing = match var.unpack() {
ty::GenericArgKind::Lifetime(re) => {
if let ty::RegionKind::ReBound(ty::INNERMOST, bv) = re.kind() {
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
return None;
}
}
ty::GenericArgKind::Type(ty) => {
if let ty::Bound(ty::INNERMOST, bv) = *ty.kind() {
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
return None;
}
}
ty::GenericArgKind::Const(ct) => {
if let ty::ConstKind::Bound(ty::INNERMOST, bv) = ct.kind() {
mapping.insert(bv, tcx.mk_param_from_def(param))
} else {
return None;
}
}
};
if existing.is_some() {
return None;
}
}
// Finally, map all of the args in the GAT to the params we expect, and compress
// the remaining late-bound vars so that they count up from var 0.
let mut folder =
MapAndCompressBoundVars { tcx, binder: ty::INNERMOST, still_bound_vars: vec![], mapping };
let pred = clause.kind().skip_binder().fold_with(&mut folder);
Some((
ty::Binder::bind_with_vars(pred, tcx.mk_bound_variable_kinds(&folder.still_bound_vars))
.upcast(tcx),
span,
))
}
/// Given some where clause like `for<'b, 'c> <Self as Trait<'a_identity>>::Gat<'b>: Bound<'c>`,
/// the mapping will map `'b` back to the GAT's `'b_identity`. Then we need to compress the
/// remaining bound var `'c` to index 0.
///
/// This folder gives us: `for<'c> <Self as Trait<'a_identity>>::Gat<'b_identity>: Bound<'c>`,
/// which is sufficient for an item bound for `Gat`, since all of the GAT's args are identity.
struct MapAndCompressBoundVars<'tcx> {
tcx: TyCtxt<'tcx>,
/// How deep are we? Makes sure we don't touch the vars of nested binders.
binder: ty::DebruijnIndex,
/// List of bound vars that remain unsubstituted because they were not
/// mentioned in the GAT's args.
still_bound_vars: Vec<ty::BoundVariableKind>,
/// Subtle invariant: If the `GenericArg` is bound, then it should be
/// stored with the debruijn index of `INNERMOST` so it can be shifted
/// correctly during substitution.
mapping: FxIndexMap<ty::BoundVar, ty::GenericArg<'tcx>>,
}
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
ty::Binder<'tcx, T>: TypeSuperFoldable<TyCtxt<'tcx>>,
{
self.binder.shift_in(1);
let out = t.super_fold_with(self);
self.binder.shift_out(1);
out
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if !ty.has_bound_vars() {
return ty;
}
if let ty::Bound(binder, old_bound) = *ty.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) {
mapped.expect_ty()
} else {
// If we didn't find a mapped generic, then make a new one.
// Allocate a new var idx, and insert a new bound ty.
let var = ty::BoundVar::from_usize(self.still_bound_vars.len());
self.still_bound_vars.push(ty::BoundVariableKind::Ty(old_bound.kind));
let mapped = Ty::new_bound(self.tcx, ty::INNERMOST, ty::BoundTy {
var,
kind: old_bound.kind,
});
self.mapping.insert(old_bound.var, mapped.into());
mapped
};
shift_vars(self.tcx, mapped, self.binder.as_u32())
} else {
ty.super_fold_with(self)
}
}
fn fold_region(&mut self, re: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReBound(binder, old_bound) = re.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) {
mapped.expect_region()
} else {
let var = ty::BoundVar::from_usize(self.still_bound_vars.len());
self.still_bound_vars.push(ty::BoundVariableKind::Region(old_bound.kind));
let mapped = ty::Region::new_bound(self.tcx, ty::INNERMOST, ty::BoundRegion {
var,
kind: old_bound.kind,
});
self.mapping.insert(old_bound.var, mapped.into());
mapped
};
shift_vars(self.tcx, mapped, self.binder.as_u32())
} else {
re
}
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
if !ct.has_bound_vars() {
return ct;
}
if let ty::ConstKind::Bound(binder, old_var) = ct.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_var) {
mapped.expect_const()
} else {
let var = ty::BoundVar::from_usize(self.still_bound_vars.len());
self.still_bound_vars.push(ty::BoundVariableKind::Const);
let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, var);
self.mapping.insert(old_var, mapped.into());
mapped
};
shift_vars(self.tcx, mapped, self.binder.as_u32())
} else {
ct.super_fold_with(self)
}
}
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
if !p.has_bound_vars() { p } else { p.super_fold_with(self) }
}
}
/// Opaque types don't inherit bounds from their parent: for return position
/// impl trait it isn't possible to write a suitable predicate on the
/// containing function and for type-alias impl trait we don't have a backwards

View file

@ -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};
@ -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();
}

View file

@ -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

View file

@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![feature(decl_macro)]
#![feature(file_buffered)]
#![feature(let_chains)]
#![feature(try_blocks)]
#![warn(unreachable_pub)]

View file

@ -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)?;
}
}

View file

@ -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(())

View file

@ -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)]

View file

@ -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)]

View file

@ -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}"))
})?))
})?)
}
///////////////////////////////////////////////////////////////////////////

View file

@ -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 {
@ -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) => {

View file

@ -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)]

View file

@ -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");

View file

@ -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)]

View file

@ -4,7 +4,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::LangItem;
use rustc_index::IndexVec;
use rustc_index::bit_set::BitSet;
use rustc_infer::traits::Reveal;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{Obligation, ObligationCause, Reveal};
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@ -16,6 +17,8 @@ use rustc_middle::ty::{
use rustc_middle::{bug, span_bug};
use rustc_target::abi::{FIRST_VARIANT, Size};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_type_ir::Upcast;
use crate::util::{is_within_packed, relate_types};
@ -586,6 +589,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
}
/// Check that the given predicate definitely holds in the param-env of this MIR body.
fn predicate_must_hold_modulo_regions(
&self,
pred: impl Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
) -> bool {
let infcx = self.tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),
self.param_env,
pred,
));
ocx.select_all_or_error().is_empty()
}
}
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
@ -1202,8 +1221,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
// This is used for all `CoerceUnsized` types,
// not just pointers/references, so is hard to check.
// Pointers being unsize coerced should at least implement
// `CoerceUnsized`.
if !self.predicate_must_hold_modulo_regions(ty::TraitRef::new(
self.tcx,
self.tcx.require_lang_item(
LangItem::CoerceUnsized,
Some(self.body.source_info(location).span),
),
[op_ty, *target_type],
)) {
self.fail(location, format!("Unsize coercion, but `{op_ty}` isn't coercible to `{target_type}`"));
}
}
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
// FIXME(dyn-star): make sure nothing needs to be done here.

View file

@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![feature(array_windows)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![warn(unreachable_pub)]

View file

@ -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};
@ -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();

View file

@ -1840,6 +1840,8 @@ supported_targets! {
("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
("riscv32-wrs-vxworks", riscv32_wrs_vxworks),
("riscv64-wrs-vxworks", riscv64_wrs_vxworks),
("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3),
("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),

View file

@ -5,8 +5,7 @@ pub(crate) fn target() -> Target {
base.max_atomic_width = Some(128);
Target {
// LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
llvm_target: "aarch64-unknown-linux-musl".into(),
llvm_target: "aarch64-unknown-linux-ohos".into(),
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 OpenHarmony".into()),
tier: Some(2),

View file

@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
description: None,
tier: Some(3),
host_tools: Some(false),
std: None, // ?
std: Some(true),
},
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),

View file

@ -7,8 +7,7 @@ pub(crate) fn target() -> Target {
// Most of these settings are copied from the armv7_unknown_linux_musleabi
// target.
Target {
// LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
llvm_target: "armv7-unknown-linux-gnueabi".into(),
llvm_target: "armv7-unknown-linux-ohos".into(),
metadata: crate::spec::TargetMetadata {
description: Some("Armv7-A OpenHarmony".into()),
tier: Some(2),

View file

@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
description: None,
tier: Some(3),
host_tools: Some(false),
std: None, // ?
std: Some(true),
},
pointer_width: 32,
data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\

View file

@ -2,8 +2,7 @@ use crate::spec::{Target, TargetOptions, base};
pub(crate) fn target() -> Target {
Target {
// LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
llvm_target: "loongarch64-unknown-linux-musl".into(),
llvm_target: "loongarch64-unknown-linux-ohos".into(),
metadata: crate::spec::TargetMetadata {
description: Some("LoongArch64 OpenHarmony".into()),
tier: Some(3),

View file

@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
description: None,
tier: Some(3),
host_tools: Some(false),
std: None, // ?
std: Some(true),
},
pointer_width: 64,
data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),

View file

@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
description: None,
tier: Some(3),
host_tools: Some(false),
std: None, // ?
std: Some(true),
},
pointer_width: 32,
data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),

View file

@ -0,0 +1,24 @@
use crate::spec::{StackProbeType, Target, TargetOptions, base};
pub(crate) fn target() -> Target {
Target {
llvm_target: "riscv32".into(),
metadata: crate::spec::TargetMetadata {
description: None,
tier: Some(3),
host_tools: Some(false),
std: Some(true),
},
pointer_width: 32,
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
arch: "riscv32".into(),
options: TargetOptions {
cpu: "generic-rv32".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
features: "+m,+a,+f,+d,+c".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},
}
}

View file

@ -0,0 +1,24 @@
use crate::spec::{StackProbeType, Target, TargetOptions, base};
pub(crate) fn target() -> Target {
Target {
llvm_target: "riscv64".into(),
metadata: crate::spec::TargetMetadata {
description: None,
tier: Some(3),
host_tools: Some(false),
std: Some(true),
},
pointer_width: 64,
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
arch: "riscv64".into(),
options: TargetOptions {
cpu: "generic-rv64".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
features: "+m,+a,+f,+d,+c".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},
}
}

View file

@ -15,8 +15,7 @@ pub(crate) fn target() -> Target {
base.supports_xray = true;
Target {
// LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
llvm_target: "x86_64-unknown-linux-musl".into(),
llvm_target: "x86_64-unknown-linux-ohos".into(),
metadata: crate::spec::TargetMetadata {
description: Some("x86_64 OpenHarmony".into()),
tier: Some(2),

View file

@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
description: None,
tier: Some(3),
host_tools: Some(false),
std: None, // ?
std: Some(true),
},
pointer_width: 64,
data_layout:

View file

@ -1,4 +1,4 @@
#![cfg_attr(feature = "optimize_for_size", allow(dead_code))]
#![cfg_attr(any(feature = "optimize_for_size", target_pointer_width = "16"), allow(dead_code))]
use crate::marker::Freeze;

View file

@ -1,22 +1,22 @@
//! This module contains the entry points for `slice::sort`.
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
use crate::cmp;
use crate::intrinsics;
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
use crate::slice::sort::shared::smallsort::{
SMALL_SORT_GENERAL_SCRATCH_LEN, StableSmallSortTypeImpl, insertion_sort_shift_left,
};
pub(crate) mod merge;
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
pub(crate) mod drift;
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
pub(crate) mod quicksort;
#[cfg(feature = "optimize_for_size")]
#[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))]
pub(crate) mod tiny;
/// Stable sort called driftsort by Orson Peters and Lukas Bergdoll.
@ -45,7 +45,7 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
cfg_if! {
if #[cfg(target_pointer_width = "16")] {
let heap_buf = BufT::with_capacity(alloc_len);
let mut heap_buf = BufT::with_capacity(alloc_len);
let scratch = heap_buf.as_uninit_slice_mut();
} else {
// For small inputs 4KiB of stack storage suffices, which allows us to avoid
@ -85,7 +85,7 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
///
/// Deliberately don't inline the main sorting routine entrypoint to ensure the
/// inlined insertion sort i-cache footprint remains minimal.
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
#[inline(never)]
fn driftsort_main<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less: &mut F) {
// By allocating n elements of memory we can ensure the entire input can

View file

@ -2,9 +2,9 @@
use crate::intrinsics;
use crate::mem::SizedTypeProperties;
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
use crate::slice::sort::shared::find_existing_run;
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
use crate::slice::sort::shared::smallsort::insertion_sort_shift_left;
pub(crate) mod heapsort;
@ -55,7 +55,7 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) {
///
/// Deliberately don't inline the main sorting routine entrypoint to ensure the
/// inlined insertion sort i-cache footprint remains minimal.
#[cfg(not(feature = "optimize_for_size"))]
#[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
#[inline(never)]
fn ipnsort<T, F>(v: &mut [T], is_less: &mut F)
where

View file

@ -48,7 +48,7 @@ cfg_if::cfg_if! {
target_os = "psp",
target_os = "xous",
target_os = "solid_asp3",
all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems"))),
all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems", target_os = "nuttx"))),
all(target_vendor = "fortanix", target_env = "sgx"),
target_family = "wasm",
))] {

View file

@ -54,6 +54,7 @@ fn main() {
|| target_os == "teeos"
|| target_os == "zkvm"
|| target_os == "rtems"
|| target_os == "nuttx"
// See src/bootstrap/src/core/build_steps/synthetic_targets.rs
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()

View file

@ -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`].
///
/// # 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,
@ -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

View file

@ -74,6 +74,14 @@ impl<R: Read> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}
pub(crate) fn try_new_buffer() -> io::Result<Buffer> {
Buffer::try_with_capacity(DEFAULT_BUF_SIZE)
}
pub(crate) fn with_buffer(inner: R, buf: Buffer) -> Self {
Self { inner, buf }
}
/// Creates a new `BufReader<R>` with the specified buffer capacity.
///
/// # Examples

View file

@ -10,7 +10,7 @@
//! without encountering any runtime bounds checks.
use crate::cmp;
use crate::io::{self, BorrowedBuf, Read};
use crate::io::{self, BorrowedBuf, ErrorKind, Read};
use crate::mem::MaybeUninit;
pub struct Buffer {
@ -36,6 +36,16 @@ impl Buffer {
Self { buf, pos: 0, filled: 0, initialized: 0 }
}
#[inline]
pub fn try_with_capacity(capacity: usize) -> io::Result<Self> {
match Box::try_new_uninit_slice(capacity) {
Ok(buf) => Ok(Self { buf, pos: 0, filled: 0, initialized: 0 }),
Err(_) => {
Err(io::const_io_error!(ErrorKind::OutOfMemory, "failed to allocate read buffer"))
}
}
}
#[inline]
pub fn buffer(&self) -> &[u8] {
// SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and

View file

@ -94,6 +94,16 @@ impl<W: Write> BufWriter<W> {
BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
}
pub(crate) fn try_new_buffer() -> io::Result<Vec<u8>> {
Vec::try_with_capacity(DEFAULT_BUF_SIZE).map_err(|_| {
io::const_io_error!(ErrorKind::OutOfMemory, "failed to allocate write buffer")
})
}
pub(crate) fn with_buffer(inner: W, buf: Vec<u8>) -> Self {
Self { inner, buf, panicked: false }
}
/// Creates a new `BufWriter<W>` with at least the specified buffer capacity.
///
/// # Examples

View file

@ -402,7 +402,7 @@ pub enum ErrorKind {
/// The operation was partially successful and needs to be checked
/// later on due to not blocking.
#[unstable(feature = "io_error_inprogress", issue = "none")]
#[unstable(feature = "io_error_inprogress", issue = "130840")]
InProgress,
// "Unusual" error kinds which do not correspond simply to (sets

View file

@ -374,6 +374,7 @@
#![feature(slice_concat_trait)]
#![feature(thin_box)]
#![feature(try_reserve_kind)]
#![feature(try_with_capacity)]
#![feature(vec_into_raw_parts)]
// tidy-alphabetical-end
//

View file

@ -139,6 +139,8 @@ pub mod macos;
pub mod netbsd;
#[cfg(target_os = "nto")]
pub mod nto;
#[cfg(target_os = "nuttx")]
pub mod nuttx;
#[cfg(target_os = "openbsd")]
pub mod openbsd;
#[cfg(target_os = "redox")]

View file

@ -0,0 +1,92 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
use crate::sys_common::AsInner;
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_dev(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ino(&self) -> u64;
#[stable(feature = "metadata_ext", since = "1.1.0")]
fn st_mode(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_nlink(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_uid(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_gid(&self) -> u32;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_rdev(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_size(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime_nsec(&self) -> i64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blksize(&self) -> u64;
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blocks(&self) -> u64;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
}
fn st_ino(&self) -> u64 {
self.as_inner().as_inner().st_ino as u64
}
fn st_mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
fn st_nlink(&self) -> u64 {
self.as_inner().as_inner().st_nlink as u64
}
fn st_uid(&self) -> u32 {
self.as_inner().as_inner().st_uid as u32
}
fn st_gid(&self) -> u32 {
self.as_inner().as_inner().st_gid as u32
}
fn st_rdev(&self) -> u64 {
self.as_inner().as_inner().st_rdev as u64
}
fn st_size(&self) -> u64 {
self.as_inner().as_inner().st_size as u64
}
fn st_atime(&self) -> i64 {
self.as_inner().as_inner().st_atim.tv_sec as i64
}
fn st_atime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_atim.tv_nsec as i64
}
fn st_mtime(&self) -> i64 {
self.as_inner().as_inner().st_mtim.tv_sec as i64
}
fn st_mtime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_mtim.tv_nsec as i64
}
fn st_ctime(&self) -> i64 {
self.as_inner().as_inner().st_ctim.tv_sec as i64
}
fn st_ctime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_ctim.tv_nsec as i64
}
fn st_blksize(&self) -> u64 {
self.as_inner().as_inner().st_blksize as u64
}
fn st_blocks(&self) -> u64 {
self.as_inner().as_inner().st_blocks as u64
}
}

View file

@ -0,0 +1,4 @@
#![stable(feature = "raw_ext", since = "1.1.0")]
#![forbid(unsafe_op_in_unsafe_fn)]
pub mod fs;
pub(crate) mod raw;

View file

@ -0,0 +1,33 @@
//! rtems raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![deprecated(
since = "1.8.0",
note = "these type aliases are no longer supported by \
the standard library, the `libc` crate on \
crates.io should be used instead for the correct \
definitions"
)]
#![allow(deprecated)]
#[stable(feature = "pthread_t", since = "1.8.0")]
pub type pthread_t = libc::pthread_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type blkcnt_t = libc::blkcnt_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type blksize_t = libc::blksize_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type dev_t = libc::dev_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type ino_t = libc::ino_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type mode_t = libc::mode_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type nlink_t = libc::nlink_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type off_t = libc::off_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type time_t = libc::time_t;

View file

@ -69,6 +69,8 @@ mod platform {
pub use crate::os::netbsd::*;
#[cfg(target_os = "nto")]
pub use crate::os::nto::*;
#[cfg(target_os = "nuttx")]
pub use crate::os::nuttx::*;
#[cfg(target_os = "openbsd")]
pub use crate::os::openbsd::*;
#[cfg(target_os = "redox")]

View file

@ -71,7 +71,8 @@ impl RandomSource for DefaultRandomSource {
///
/// This is a convenience function for `T::random(&mut DefaultRandomSource)` and
/// will sample according to the same distribution as the underlying [`Random`]
/// trait implementation.
/// trait implementation. See [`DefaultRandomSource`] for more information about
/// how randomness is sourced.
///
/// **Warning:** Be careful when manipulating random values! The
/// [`random`](Random::random) method on integers samples them with a uniform

View file

@ -71,6 +71,7 @@ cfg_if::cfg_if! {
}
} else {
#[inline]
#[cfg_attr(target_os = "vxworks", allow(unused_unsafe))]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
let mut out = ptr::null_mut();
// We prefer posix_memalign over aligned_alloc since it is more widely available, and

View file

@ -105,84 +105,7 @@ mod os {
}
}
#[cfg(target_os = "linux")]
mod os {
use super::DebuggerPresence;
use crate::fs::File;
use crate::io::Read;
pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
// This function is crafted with the following goals:
// * Memory efficiency: It avoids crashing the panicking process due to
// out-of-memory (OOM) conditions by not using large heap buffers or
// allocating significant stack space, which could lead to stack overflow.
// * Minimal binary size: The function uses a minimal set of facilities
// from the standard library to avoid increasing the resulting binary size.
//
// To achieve these goals, the function does not use `[std::io::BufReader]`
// and instead reads the file byte by byte using a sliding window approach.
// It's important to note that the "/proc/self/status" pseudo-file is synthesized
// by the Virtual File System (VFS), meaning it is not read from a slow or
// non-volatile storage medium so buffering might not be as beneficial because
// all data is read from memory, though this approach does incur a syscall for
// each byte read.
//
// We cannot make assumptions about the file size or the position of the
// target prefix ("TracerPid:"), so the function does not use
// `[std::fs::read_to_string]` thus not employing UTF-8 to ASCII checking,
// conversion, or parsing as we're looking for an ASCII prefix.
//
// These condiderations make the function deviate from the familiar concise pattern
// of searching for a string in a text file.
fn read_byte(file: &mut File) -> Option<u8> {
let mut buffer = [0];
file.read_exact(&mut buffer).ok()?;
Some(buffer[0])
}
// The ASCII prefix of the datum we're interested in.
const TRACER_PID: &[u8] = b"TracerPid:\t";
let mut file = File::open("/proc/self/status").ok()?;
let mut matched = 0;
// Look for the `TRACER_PID` prefix.
while let Some(byte) = read_byte(&mut file) {
if byte == TRACER_PID[matched] {
matched += 1;
if matched == TRACER_PID.len() {
break;
}
} else {
matched = 0;
}
}
// Was the prefix found?
if matched != TRACER_PID.len() {
return None;
}
// It was; get the ASCII representation of the first digit
// of the PID. That is enough to see if there is a debugger
// attached as the kernel does not pad the PID on the left
// with the leading zeroes.
let byte = read_byte(&mut file)?;
if byte.is_ascii_digit() && byte != b'0' {
Some(DebuggerPresence::Detected)
} else {
Some(DebuggerPresence::NotDetected)
}
}
}
#[cfg(not(any(
target_os = "windows",
target_vendor = "apple",
target_os = "freebsd",
target_os = "linux"
)))]
#[cfg(not(any(target_os = "windows", target_vendor = "apple", target_os = "freebsd")))]
mod os {
pub(super) fn is_debugger_present() -> Option<super::DebuggerPresence> {
None

View file

@ -113,6 +113,7 @@ impl DoubleEndedIterator for Args {
target_os = "nto",
target_os = "hurd",
target_os = "rtems",
target_os = "nuttx",
))]
mod imp {
use crate::ffi::c_char;

View file

@ -283,3 +283,14 @@ pub mod os {
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}
#[cfg(target_os = "nuttx")]
pub mod os {
pub const FAMILY: &str = "unix";
pub const OS: &str = "nuttx";
pub const DLL_PREFIX: &str = "lib";
pub const DLL_SUFFIX: &str = ".so";
pub const DLL_EXTENSION: &str = "so";
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}

View file

@ -98,7 +98,12 @@ impl FileDesc {
Ok(ret as usize)
}
#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
#[cfg(not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
)))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::readv(
@ -110,14 +115,24 @@ impl FileDesc {
Ok(ret as usize)
}
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
#[cfg(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
io::default_read_vectored(|b| self.read(b), bufs)
}
#[inline]
pub fn is_read_vectored(&self) -> bool {
cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))
cfg!(not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
)))
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@ -297,7 +312,12 @@ impl FileDesc {
Ok(ret as usize)
}
#[cfg(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))]
#[cfg(not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
)))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::writev(
@ -309,14 +329,24 @@ impl FileDesc {
Ok(ret as usize)
}
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
#[cfg(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
io::default_write_vectored(|b| self.write(b), bufs)
}
#[inline]
pub fn is_write_vectored(&self) -> bool {
cfg!(not(any(target_os = "espidf", target_os = "horizon", target_os = "vita")))
cfg!(not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
)))
}
#[cfg_attr(target_os = "vxworks", allow(unused_unsafe))]

View file

@ -479,6 +479,7 @@ impl FileAttr {
target_os = "vita",
target_os = "hurd",
target_os = "rtems",
target_os = "nuttx",
)))]
pub fn modified(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
@ -501,7 +502,7 @@ impl FileAttr {
SystemTime::new(self.stat.st_mtime as i64, 0)
}
#[cfg(any(target_os = "horizon", target_os = "hurd"))]
#[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
pub fn modified(&self) -> io::Result<SystemTime> {
SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64)
}
@ -513,6 +514,7 @@ impl FileAttr {
target_os = "vita",
target_os = "hurd",
target_os = "rtems",
target_os = "nuttx",
)))]
pub fn accessed(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
@ -535,7 +537,7 @@ impl FileAttr {
SystemTime::new(self.stat.st_atime as i64, 0)
}
#[cfg(any(target_os = "horizon", target_os = "hurd"))]
#[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
pub fn accessed(&self) -> io::Result<SystemTime> {
SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64)
}
@ -866,6 +868,7 @@ impl Drop for Dir {
target_os = "horizon",
target_os = "vxworks",
target_os = "rtems",
target_os = "nuttx",
)))]
{
let fd = unsafe { libc::dirfd(self.0) };
@ -1000,6 +1003,13 @@ impl DirEntry {
self.entry.d_fileno as u64
}
#[cfg(target_os = "nuttx")]
pub fn ino(&self) -> u64 {
// Leave this 0 for now, as NuttX does not provide an inode number
// in its directory entries.
0
}
#[cfg(any(
target_os = "netbsd",
target_os = "openbsd",
@ -1327,7 +1337,8 @@ impl File {
target_os = "redox",
target_os = "espidf",
target_os = "horizon",
target_os = "vxworks"
target_os = "vxworks",
target_os = "nuttx",
)))]
let to_timespec = |time: Option<SystemTime>| match time {
Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts),
@ -1342,7 +1353,7 @@ impl File {
None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
};
cfg_if::cfg_if! {
if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "vxworks"))] {
if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "vxworks", target_os = "nuttx"))] {
// Redox doesn't appear to support `UTIME_OMIT`.
// ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
// the same as for Redox.

View file

@ -222,6 +222,7 @@ static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
target_os = "horizon",
target_os = "vxworks",
target_os = "vita",
target_os = "nuttx",
)))]
pub(crate) fn on_broken_pipe_flag_used() -> bool {
ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed)
@ -425,7 +426,7 @@ cfg_if::cfg_if! {
}
}
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))]
mod unsupported {
use crate::io;

View file

@ -38,19 +38,19 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
// We may need to trigger a glibc workaround. See on_resolver_failure() for details.
on_resolver_failure();
#[cfg(not(target_os = "espidf"))]
#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
if err == libc::EAI_SYSTEM {
return Err(io::Error::last_os_error());
}
#[cfg(not(target_os = "espidf"))]
#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
let detail = unsafe {
// We can't always expect a UTF-8 environment. When we don't get that luxury,
// it's better to give a low-quality error message than none at all.
CStr::from_ptr(libc::gai_strerror(err)).to_string_lossy()
};
#[cfg(target_os = "espidf")]
#[cfg(any(target_os = "espidf", target_os = "nuttx"))]
let detail = "";
Err(io::Error::new(

View file

@ -48,6 +48,7 @@ extern "C" {
target_os = "openbsd",
target_os = "android",
target_os = "redox",
target_os = "nuttx",
target_env = "newlib"
),
link_name = "__errno"
@ -399,6 +400,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
target_os = "linux",
target_os = "hurd",
target_os = "android",
target_os = "nuttx",
target_os = "emscripten"
))]
pub fn current_exe() -> io::Result<PathBuf> {
@ -717,6 +719,7 @@ pub fn home_dir() -> Option<PathBuf> {
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx",
all(target_vendor = "apple", not(target_os = "macos")),
))]
unsafe fn fallback() -> Option<OsString> {
@ -730,6 +733,7 @@ pub fn home_dir() -> Option<PathBuf> {
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx",
all(target_vendor = "apple", not(target_os = "macos")),
)))]
unsafe fn fallback() -> Option<OsString> {

View file

@ -2,10 +2,10 @@ pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes
pub use self::process_inner::{ExitStatus, ExitStatusError, Process};
pub use crate::ffi::OsString as EnvKey;
#[cfg_attr(any(target_os = "espidf", target_os = "horizon"), allow(unused))]
#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))]
mod process_common;
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))]
mod process_unsupported;
cfg_if::cfg_if! {
@ -16,7 +16,7 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "vxworks")] {
#[path = "process_vxworks.rs"]
mod process_inner;
} else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
} else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] {
mod process_inner {
pub use super::process_unsupported::*;
}

View file

@ -140,7 +140,12 @@ impl Thread {
}
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
#[cfg(any(
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "nuttx"
))]
pub fn set_name(name: &CStr) {
unsafe {
libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr());
@ -517,7 +522,7 @@ mod cgroups {
use crate::borrow::Cow;
use crate::ffi::OsString;
use crate::fs::{File, exists};
use crate::io::{BufRead, BufReader, Read};
use crate::io::{BufRead, Read};
use crate::os::unix::ffi::OsStringExt;
use crate::path::{Path, PathBuf};
use crate::str::from_utf8;
@ -690,7 +695,7 @@ mod cgroups {
/// If the cgroupfs is a bind mount then `group_path` is adjusted to skip
/// over the already-included prefix
fn find_mountpoint(group_path: &Path) -> Option<(Cow<'static, str>, &Path)> {
let mut reader = BufReader::new(File::open("/proc/self/mountinfo").ok()?);
let mut reader = File::open_buffered("/proc/self/mountinfo").ok()?;
let mut line = String::with_capacity(256);
loop {
line.clear();
@ -747,12 +752,15 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
}
// No point in looking up __pthread_get_minstack() on non-glibc platforms.
#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))]
#[cfg(all(
not(all(target_os = "linux", target_env = "gnu")),
not(any(target_os = "netbsd", target_os = "nuttx"))
))]
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
libc::PTHREAD_STACK_MIN
}
#[cfg(target_os = "netbsd")]
#[cfg(any(target_os = "netbsd", target_os = "nuttx"))]
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
static STACK: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new();

View file

@ -31,7 +31,7 @@ cfg_if::cfg_if! {
target_os = "psp",
target_os = "xous",
target_os = "solid_asp3",
all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems")),
all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems"), not(target_os = "nuttx")),
all(target_vendor = "fortanix", target_env = "sgx"),
))] {
mod gcc;

View file

@ -42,6 +42,7 @@ cfg_if::cfg_if! {
target_os = "hurd",
target_os = "l4re",
target_os = "nto",
target_os = "nuttx",
))] {
mod unix_legacy;
pub use unix_legacy::fill_bytes;

View file

@ -21,6 +21,7 @@ cfg_if::cfg_if! {
target_os = "haiku",
target_os = "l4re",
target_os = "nto",
target_os = "nuttx",
target_vendor = "apple",
))] {
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;

View file

@ -18,6 +18,7 @@
#![doc(test(attr(deny(warnings))))]
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![feature(file_buffered)]
#![feature(internal_output_capture)]
#![feature(staged_api)]
#![feature(process_exitcode_internals)]

View file

@ -3,9 +3,8 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::Path;
use std::{env, error, fmt};
use std::{env, error, fmt, io};
use parm::{Param, Variables, expand};
use parser::compiled::{msys_terminfo, parse};
@ -102,8 +101,7 @@ impl TermInfo {
}
// Keep the metadata small
fn _from_path(path: &Path) -> Result<TermInfo, Error> {
let file = File::open(path).map_err(Error::IoError)?;
let mut reader = BufReader::new(file);
let mut reader = File::open_buffered(path).map_err(Error::IoError)?;
parse(&mut reader, false).map_err(Error::MalformedTerminfo)
}
}

View file

@ -23,6 +23,7 @@ cfg_if::cfg_if! {
target_os = "none",
target_os = "espidf",
target_os = "rtems",
target_os = "nuttx",
))] {
// These "unix" family members do not have unwinder.
} else if #[cfg(any(

View file

@ -358,12 +358,14 @@ target | std | host | notes
[`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
[`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
[`riscv32imafc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
[`riscv32-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android
[`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, musl 1.2.3)
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+

View file

@ -14,6 +14,8 @@ Target triplets available:
- `powerpc-wrs-vxworks`
- `powerpc64-wrs-vxworks`
- `powerpc-wrs-vxworks-spe`
- `riscv32-wrs-vxworks`
- `riscv64-wrs-vxworks`
## Target maintainers

View file

@ -16,7 +16,7 @@
use std::cell::RefCell;
use std::ffi::OsString;
use std::fs::File;
use std::io::{self, BufWriter, Write as _};
use std::io::{self, Write as _};
use std::iter::once;
use std::marker::PhantomData;
use std::path::{Component, Path, PathBuf};
@ -1020,8 +1020,7 @@ where
for part in parts {
template.append(part);
}
let file = try_err!(File::create(&path), &path);
let mut file = BufWriter::new(file);
let mut file = try_err!(File::create_buffered(&path), &path);
try_err!(write!(file, "{template}"), &path);
try_err!(file.flush(), &path);
}

View file

@ -286,7 +286,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
self.serialize_and_write(
output_crate,
BufWriter::new(try_err!(File::create(&p), p)),
try_err!(File::create_buffered(&p), p),
&p.display().to_string(),
)
} else {

View file

@ -5,6 +5,7 @@
#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]

View file

@ -25,16 +25,15 @@ if [[ $BETA = "true" ]]; then
fi
# Generate version index that is shown as root index page
cp util/gh-pages/versions.html out/index.html
echo "Making the versions.json file"
python3 ./util/versions.py out
python3 ./util/versions.py ./util/gh-pages/versions.html out
# Now let's go have some fun with the cloned repo
cd out
git config user.name "GHA CI"
git config user.email "gha@ci.invalid"
git status
if [[ -n $TAG_NAME ]]; then
# track files, so that the following check works
git add --intent-to-add "$TAG_NAME"
@ -46,8 +45,6 @@ if [[ -n $TAG_NAME ]]; then
git add "$TAG_NAME"
# Update the symlink
git add stable
# Update versions file
git add versions.json
git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
elif [[ $BETA = "true" ]]; then
if git diff --exit-code --quiet -- beta/; then

View file

@ -162,7 +162,7 @@ jobs:
find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf
- name: Upload Binaries
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: binaries
path: target/debug
@ -202,7 +202,7 @@ jobs:
# Download
- name: Download target dir
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: binaries
path: target/debug

View file

@ -6,7 +6,61 @@ document.
## Unreleased / Beta / In Rust Nightly
[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master)
[b794b8e0...master](https://github.com/rust-lang/rust-clippy/compare/b794b8e0...master)
## Rust 1.81
Current stable, released 2024-09-05
### New Lints
* Added [`cfg_not_test`] to `restriction`
[#11293](https://github.com/rust-lang/rust-clippy/pull/11293)
* Added [`byte_char_slices`] to `style`
[#10155](https://github.com/rust-lang/rust-clippy/pull/10155)
* Added [`set_contains_or_insert`] to `nursery`
[#12873](https://github.com/rust-lang/rust-clippy/pull/12873)
* Added [`manual_rotate`] to `style`
[#12983](https://github.com/rust-lang/rust-clippy/pull/12983)
* Added [`unnecessary_min_or_max`] to `complexity`
[#12368](https://github.com/rust-lang/rust-clippy/pull/12368)
* Added [`manual_inspect`] to `complexity`
[#12287](https://github.com/rust-lang/rust-clippy/pull/12287)
* Added [`field_scoped_visibility_modifiers`] to `restriction`
[#12893](https://github.com/rust-lang/rust-clippy/pull/12893)
* Added [`manual_pattern_char_comparison`] to `style`
[#12849](https://github.com/rust-lang/rust-clippy/pull/12849)
* Added [`needless_maybe_sized`] to `suspicious`
[#10632](https://github.com/rust-lang/rust-clippy/pull/10632)
* Added [`needless_character_iteration`] to `suspicious`
[#12815](https://github.com/rust-lang/rust-clippy/pull/12815)
### Moves and Deprecations
* [`allow_attributes`], [`allow_attributes_without_reason`]: Now work on stable
[rust#120924](https://github.com/rust-lang/rust/pull/120924)
* Renamed `overflow_check_conditional` to [`panicking_overflow_checks`]
[#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now deny-by-default)
[#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
* Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`]
[#12974](https://github.com/rust-lang/rust-clippy/pull/12974)
* Deprecated [`maybe_misused_cfg`] and [`mismatched_target_os`] as they are now caught by cargo
and rustc
[#12875](https://github.com/rust-lang/rust-clippy/pull/12875)
### Enhancements
* [`significant_drop_in_scrutinee`]: Now also checks scrutinies of `while let` and `for let`
expressions
[#12870](https://github.com/rust-lang/rust-clippy/pull/12870)
* [`std_instead_of_core`]: Now respects the `msrv` configuration
[#13168](https://github.com/rust-lang/rust-clippy/pull/13168)
### ICE Fixes
* [`suboptimal_flops`]: No longer crashes on custom `.log()` functions
[#12884](https://github.com/rust-lang/rust-clippy/pull/12884)
## Rust 1.80
@ -5500,6 +5554,7 @@ Released 2018-09-13
[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub
[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
@ -5559,6 +5614,7 @@ Released 2018-09-13
[`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits
[`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals
[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp
[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil
[`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
@ -5570,6 +5626,7 @@ Released 2018-09-13
[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
[`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite
[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two
[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
@ -5716,6 +5773,7 @@ Released 2018-09-13
[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_zero_suggestions
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
@ -5757,6 +5815,7 @@ Released 2018-09-13
[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block
[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
@ -5962,6 +6021,7 @@ Released 2018-09-13
[`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
[`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_first_then_check
[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
[`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check
[`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join
@ -6003,6 +6063,7 @@ Released 2018-09-13
[`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_result_ok
[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
[`unused_trait_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
@ -6013,6 +6074,7 @@ Released 2018-09-13
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items
[`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
[`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
@ -6047,6 +6109,7 @@ Released 2018-09-13
[`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects
[`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values
[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes
[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
<!-- end autogenerated links to lint list -->
<!-- begin autogenerated links to configuration documentation -->

View file

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.1.82"
version = "0.1.83"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@ -31,7 +31,7 @@ anstream = "0.6.0"
[dev-dependencies]
cargo_metadata = "0.18.1"
ui_test = "0.25"
ui_test = "0.26.4"
regex = "1.5.5"
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.122"

View file

@ -727,6 +727,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
* [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names)
* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)

View file

@ -1,6 +1,6 @@
[package]
name = "clippy_config"
version = "0.1.82"
version = "0.1.83"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,6 +1,6 @@
use crate::ClippyConfiguration;
use crate::msrvs::Msrv;
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
use crate::ClippyConfiguration;
use rustc_errors::Applicability;
use rustc_session::Session;
use rustc_span::edit_distance::edit_distance;
@ -563,6 +563,7 @@ define_Conf! {
uninlined_format_args,
unnecessary_lazy_evaluations,
unnested_or_patterns,
unused_trait_names,
use_self,
)]
msrv: Msrv = Msrv::empty(),
@ -864,7 +865,7 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
cmp::max(1, terminal_width / (SEPARATOR_WIDTH + max_field_width))
});
let rows = (fields.len() + (columns - 1)) / columns;
let rows = fields.len().div_ceil(columns);
let column_widths = (0..columns)
.map(|column| {

View file

@ -26,5 +26,5 @@ mod metadata;
pub mod msrvs;
pub mod types;
pub use conf::{get_configuration_metadata, lookup_conf_file, Conf};
pub use conf::{Conf, get_configuration_metadata, lookup_conf_file};
pub use metadata::ClippyConfiguration;

View file

@ -1,7 +1,7 @@
use rustc_ast::Attribute;
use rustc_attr::parse_version;
use rustc_session::{RustcVersion, Session};
use rustc_span::{sym, Symbol};
use rustc_span::{Symbol, sym};
use serde::Deserialize;
use std::fmt;
@ -23,6 +23,7 @@ msrv_aliases! {
1,80,0 { BOX_INTO_ITER}
1,77,0 { C_STR_LITERALS }
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
1,73,0 { MANUAL_DIV_CEIL }
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
1,68,0 { PATH_MAIN_SEPARATOR_STR }
@ -38,7 +39,7 @@ msrv_aliases! {
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
1,50,0 { BOOL_THEN, CLAMP }
1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN, SATURATING_SUB_CONST }
1,46,0 { CONST_IF_MATCH }
1,45,0 { STR_STRIP_PREFIX }
1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS }
@ -50,6 +51,7 @@ msrv_aliases! {
1,36,0 { ITERATOR_COPIED }
1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
1,34,0 { TRY_FROM }
1,33,0 { UNDERSCORE_IMPORTS }
1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
1,29,0 { ITER_FLATTEN }
1,28,0 { FROM_BOOL }

View file

@ -1,5 +1,5 @@
use serde::de::{self, Deserializer, Visitor};
use serde::{ser, Deserialize, Serialize};
use serde::{Deserialize, Serialize, ser};
use std::fmt;
#[derive(Debug, Deserialize)]

View file

@ -1,6 +1,6 @@
use crate::clippy_project_root;
use itertools::Itertools;
use rustc_lexer::{tokenize, TokenKind};
use rustc_lexer::{TokenKind, tokenize};
use shell_escape::escape;
use std::ffi::{OsStr, OsString};
use std::ops::ControlFlow;

View file

@ -441,7 +441,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
#[allow(clippy::too_many_lines)]
fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> {
use super::update_lints::{match_tokens, LintDeclSearchResult};
use super::update_lints::{LintDeclSearchResult, match_tokens};
use rustc_lexer::TokenKind;
let lint_name_upper = lint.name.to_uppercase();

View file

@ -29,7 +29,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
}
if let Some(url) = url.take() {
thread::spawn(move || {
Command::new(PYTHON)
let mut child = Command::new(PYTHON)
.arg("-m")
.arg("http.server")
.arg(port.to_string())
@ -40,6 +40,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
thread::sleep(Duration::from_millis(500));
// Launch browser after first export.py has completed and http.server is up
let _result = opener::open(url);
child.wait().unwrap();
});
}
thread::sleep(Duration::from_millis(1000));

View file

@ -1,7 +1,7 @@
use crate::clippy_project_root;
use aho_corasick::AhoCorasickBuilder;
use itertools::Itertools;
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape};
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::fmt::{self, Write};
@ -1048,23 +1048,17 @@ mod tests {
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
];
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
expected.insert(
"group1".to_string(),
vec![
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
],
);
expected.insert(
"group2".to_string(),
vec![Lint::new(
"should_assert_eq2",
"group2",
"\"abc\"",
"module_name",
Range::default(),
)],
);
expected.insert("group1".to_string(), vec![
Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
]);
expected.insert("group2".to_string(), vec![Lint::new(
"should_assert_eq2",
"group2",
"\"abc\"",
"module_name",
Range::default(),
)]);
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "clippy_lints"
version = "0.1.82"
version = "0.1.83"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"

Some files were not shown because too many files have changed in this diff Show more