Auto merge of #135947 - matthiaskrgr:rollup-k9jpfls, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #135073 (Implement `ByteStr` and `ByteString` types)
 - #135492 (Add missing check for async body when suggesting await on futures.)
 - #135766 (handle global trait bounds defining assoc types)
 - #135880 (Get rid of RunCompiler)
 - #135908 (rustc_codegen_llvm: remove outdated asm-to-obj codegen note)
 - #135911 (Allow `arena_cache` queries to return `Option<&'tcx T>`)
 - #135920 (simplify parse_format::Parser::ws by using next_if)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-01-24 01:59:34 +00:00
commit 1c9837df1d
42 changed files with 1609 additions and 251 deletions

View file

@ -4260,7 +4260,6 @@ dependencies = [
"rustc_serialize",
"rustc_type_ir",
"rustc_type_ir_macros",
"smallvec",
"tracing",
]

View file

@ -769,12 +769,9 @@ pub(crate) unsafe fn codegen(
}
}
// Two things to note:
// - If object files are just LLVM bitcode we write bitcode, copy it to
// the .o file, and delete the bitcode if it wasn't otherwise
// requested.
// - If we don't have the integrated assembler then we need to emit
// asm from LLVM and use `gcc` to create the object file.
// Note that if object files are just LLVM bitcode we write bitcode,
// copy it to the .o file, and delete the bitcode if it wasn't
// otherwise requested.
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
let bc_summary_out =

View file

@ -28,8 +28,8 @@ use std::io::{self, IsTerminal, Read, Write};
use std::panic::{self, PanicHookInfo, catch_unwind};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use std::sync::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, OnceLock};
use std::time::{Instant, SystemTime};
use std::{env, str};
@ -60,7 +60,6 @@ use rustc_session::lint::{Lint, LintId};
use rustc_session::output::collect_crate_types;
use rustc_session::{EarlyDiagCtxt, Session, config, filesearch};
use rustc_span::FileName;
use rustc_span::source_map::FileLoader;
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTuple};
use time::OffsetDateTime;
@ -208,84 +207,7 @@ pub fn diagnostics_registry() -> Registry {
}
/// This is the primary entry point for rustc.
pub struct RunCompiler<'a> {
at_args: &'a [String],
callbacks: &'a mut (dyn Callbacks + Send),
file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
make_codegen_backend:
Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
using_internal_features: Arc<std::sync::atomic::AtomicBool>,
}
impl<'a> RunCompiler<'a> {
pub fn new(at_args: &'a [String], callbacks: &'a mut (dyn Callbacks + Send)) -> Self {
Self {
at_args,
callbacks,
file_loader: None,
make_codegen_backend: None,
using_internal_features: Arc::default(),
}
}
/// Set a custom codegen backend.
///
/// Has no uses within this repository, but is used by bjorn3 for "the
/// hotswapping branch of cg_clif" for "setting the codegen backend from a
/// custom driver where the custom codegen backend has arbitrary data."
/// (See #102759.)
pub fn set_make_codegen_backend(
&mut self,
make_codegen_backend: Option<
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
) -> &mut Self {
self.make_codegen_backend = make_codegen_backend;
self
}
/// Load files from sources other than the file system.
///
/// Has no uses within this repository, but may be used in the future by
/// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
/// running rustc without having to save". (See #102759.)
pub fn set_file_loader(
&mut self,
file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
) -> &mut Self {
self.file_loader = file_loader;
self
}
/// Set the session-global flag that checks whether internal features have been used,
/// suppressing the message about submitting an issue in ICEs when enabled.
#[must_use]
pub fn set_using_internal_features(mut self, using_internal_features: Arc<AtomicBool>) -> Self {
self.using_internal_features = using_internal_features;
self
}
/// Parse args and run the compiler.
pub fn run(self) {
run_compiler(
self.at_args,
self.callbacks,
self.file_loader,
self.make_codegen_backend,
self.using_internal_features,
);
}
}
fn run_compiler(
at_args: &[String],
callbacks: &mut (dyn Callbacks + Send),
file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
make_codegen_backend: Option<
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
using_internal_features: Arc<std::sync::atomic::AtomicBool>,
) {
pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) {
let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
// Throw away the first argument, the name of the binary.
@ -322,16 +244,16 @@ fn run_compiler(
output_file: ofile,
output_dir: odir,
ice_file,
file_loader,
file_loader: None,
locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(),
lint_caps: Default::default(),
psess_created: None,
hash_untracked_state: None,
register_lints: None,
override_queries: None,
make_codegen_backend,
make_codegen_backend: None,
registry: diagnostics_registry(),
using_internal_features,
using_internal_features: &USING_INTERNAL_FEATURES,
expanded_args: args,
};
@ -1350,6 +1272,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat
})
}
pub static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false);
/// Installs a panic hook that will print the ICE message on unexpected panics.
///
/// The hook is intended to be useable even by external tools. You can pass a custom
@ -1360,15 +1284,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat
/// If you have no extra info to report, pass the empty closure `|_| ()` as the argument to
/// extra_info.
///
/// Returns a flag that can be set to disable the note for submitting a bug. This can be passed to
/// [`RunCompiler::set_using_internal_features`] to let macro expansion set it when encountering
/// internal features.
///
/// A custom rustc driver can skip calling this to set up a custom ICE hook.
pub fn install_ice_hook(
bug_report_url: &'static str,
extra_info: fn(&DiagCtxt),
) -> Arc<AtomicBool> {
pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) {
// If the user has not explicitly overridden "RUST_BACKTRACE", then produce
// full backtraces. When a compiler ICE happens, we want to gather
// as much information as possible to present in the issue opened
@ -1385,8 +1302,6 @@ pub fn install_ice_hook(
}
}
let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
let using_internal_features_hook = Arc::clone(&using_internal_features);
panic::update_hook(Box::new(
move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static),
info: &PanicHookInfo<'_>| {
@ -1438,11 +1353,9 @@ pub fn install_ice_hook(
}
// Print the ICE message
report_ice(info, bug_report_url, extra_info, &using_internal_features_hook);
report_ice(info, bug_report_url, extra_info, &USING_INTERNAL_FEATURES);
},
));
using_internal_features
}
/// Prints the ICE message, including query stack, but without backtrace.
@ -1583,13 +1496,11 @@ pub fn main() -> ! {
init_rustc_env_logger(&early_dcx);
signal_handler::install();
let mut callbacks = TimePassesCallbacks::default();
let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
install_ctrlc_handler();
let exit_code = catch_with_exit_code(|| {
RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
.set_using_internal_features(using_internal_features)
.run();
run_compiler(&args::raw_args(&early_dcx)?, &mut callbacks);
Ok(())
});

View file

@ -1,6 +1,5 @@
use std::path::PathBuf;
use std::result;
use std::sync::Arc;
use rustc_ast::{LitKind, MetaItemKind, token};
use rustc_codegen_ssa::traits::CodegenBackend;
@ -309,6 +308,11 @@ pub struct Config {
pub output_dir: Option<PathBuf>,
pub output_file: Option<OutFileName>,
pub ice_file: Option<PathBuf>,
/// Load files from sources other than the file system.
///
/// Has no uses within this repository, but may be used in the future by
/// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
/// running rustc without having to save". (See #102759.)
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
/// The list of fluent resources, used for lints declared with
/// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic).
@ -337,6 +341,11 @@ pub struct Config {
pub override_queries: Option<fn(&Session, &mut Providers)>,
/// This is a callback from the driver that is called to create a codegen backend.
///
/// Has no uses within this repository, but is used by bjorn3 for "the
/// hotswapping branch of cg_clif" for "setting the codegen backend from a
/// custom driver where the custom codegen backend has arbitrary data."
/// (See #102759.)
pub make_codegen_backend:
Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
@ -346,8 +355,7 @@ pub struct Config {
/// The inner atomic value is set to true when a feature marked as `internal` is
/// enabled. Makes it so that "please report a bug" is hidden, as ICEs with
/// internal features are wontfix, and they are usually the cause of the ICEs.
/// None signifies that this is not tracked.
pub using_internal_features: Arc<std::sync::atomic::AtomicBool>,
pub using_internal_features: &'static std::sync::atomic::AtomicBool,
/// All commandline args used to invoke the compiler, with @file args fully expanded.
/// This will only be used within debug info, e.g. in the pdb file on windows

View file

@ -2,7 +2,7 @@
use std::collections::{BTreeMap, BTreeSet};
use std::num::NonZero;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::emitter::HumanReadableErrorType;
@ -62,6 +62,8 @@ where
temps_dir,
};
static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false);
let sess = build_session(
early_dcx,
sessopts,
@ -74,7 +76,7 @@ where
sysroot,
"",
None,
Arc::default(),
&USING_INTERNAL_FEATURES,
Default::default(),
);
let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg"));

View file

@ -0,0 +1,47 @@
/// Helper trait that allows `arena_cache` queries to return `Option<&T>`
/// instead of `&Option<T>`, and avoid allocating `None` in the arena.
///
/// An arena-cached query must be declared to return a type that implements
/// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then
/// determines the types returned by the provider and stored in the arena,
/// and provides a function to bridge between the three types.
pub trait ArenaCached<'tcx>: Sized {
/// Type that is returned by the query provider.
type Provided;
/// Type that is stored in the arena.
type Allocated: 'tcx;
/// Takes a provided value, and allocates it in the arena (if appropriate)
/// with the help of the given `arena_alloc` closure.
fn alloc_in_arena(
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
value: Self::Provided,
) -> Self;
}
impl<'tcx, T> ArenaCached<'tcx> for &'tcx T {
type Provided = T;
type Allocated = T;
fn alloc_in_arena(
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
value: Self::Provided,
) -> Self {
// Just allocate in the arena normally.
arena_alloc(value)
}
}
impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> {
type Provided = Option<T>;
/// The provide value is `Option<T>`, but we only store `T` in the arena.
type Allocated = T;
fn alloc_in_arena(
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
value: Self::Provided,
) -> Self {
// Don't store None in the arena, and wrap the allocated reference in Some.
value.map(arena_alloc)
}
}

View file

@ -7,7 +7,6 @@
#![allow(unused_parens)]
use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
@ -85,6 +84,7 @@ use crate::ty::{
};
use crate::{dep_graph, mir, thir};
mod arena_cached;
pub mod erase;
mod keys;
pub use keys::{AsLocalKey, Key, LocalCrate};
@ -586,7 +586,7 @@ rustc_queries! {
separate_provide_extern
}
query mir_coroutine_witnesses(key: DefId) -> &'tcx Option<mir::CoroutineLayout<'tcx>> {
query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> {
arena_cache
desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
@ -2415,7 +2415,7 @@ rustc_queries! {
/// because the `ty::Ty`-based wfcheck is always run.
query diagnostic_hir_wf_check(
key: (ty::Predicate<'tcx>, WellFormedLoc)
) -> &'tcx Option<ObligationCause<'tcx>> {
) -> Option<&'tcx ObligationCause<'tcx>> {
arena_cache
eval_always
no_hash

View file

@ -289,10 +289,10 @@ macro_rules! define_callbacks {
/// This type alias specifies the type returned from query providers and the type
/// used for decoding. For regular queries this is the declared returned type `V`,
/// but `arena_cache` will use `<V as Deref>::Target` instead.
/// but `arena_cache` will use `<V as ArenaCached>::Provided` instead.
pub type ProvidedValue<'tcx> = query_if_arena!(
[$($modifiers)*]
(<$V as Deref>::Target)
(<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided)
($V)
);
@ -307,10 +307,18 @@ macro_rules! define_callbacks {
) -> Erase<Value<'tcx>> {
erase(query_if_arena!([$($modifiers)*]
{
if mem::needs_drop::<ProvidedValue<'tcx>>() {
&*_tcx.query_system.arenas.$name.alloc(value)
use $crate::query::arena_cached::ArenaCached;
if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() {
<$V as ArenaCached>::alloc_in_arena(
|v| _tcx.query_system.arenas.$name.alloc(v),
value,
)
} else {
&*_tcx.arena.dropless.alloc(value)
<$V as ArenaCached>::alloc_in_arena(
|v| _tcx.arena.dropless.alloc(v),
value,
)
}
}
(value)
@ -354,7 +362,7 @@ macro_rules! define_callbacks {
pub struct QueryArenas<'tcx> {
$($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
(TypedArena<<$V as Deref>::Target>)
(TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>)
()
),)*
}

View file

@ -13,7 +13,6 @@ rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
smallvec = "1.8.1"
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -8,7 +8,6 @@ use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::CanonicalResponse;
use rustc_type_ir::visit::TypeVisitableExt as _;
use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
use smallvec::SmallVec;
use tracing::{instrument, trace};
use crate::delegate::SolverDelegate;
@ -1199,33 +1198,42 @@ where
// nested requirements, over all others. This is a fix for #53123 and
// prevents where-bounds from accidentally extending the lifetime of a
// variable.
if candidates
.iter()
.any(|c| matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)))
{
let trivial_builtin_impls: SmallVec<[_; 1]> = candidates
.iter()
.filter(|c| {
matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
})
.map(|c| c.result)
.collect();
let mut trivial_builtin_impls = candidates.iter().filter(|c| {
matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
});
if let Some(candidate) = trivial_builtin_impls.next() {
// There should only ever be a single trivial builtin candidate
// as they would otherwise overlap.
assert_eq!(trivial_builtin_impls.len(), 1);
return if let Some(response) = self.try_merge_responses(&trivial_builtin_impls) {
Ok((response, Some(TraitGoalProvenVia::Misc)))
} else {
Ok((self.bail_with_ambiguity(&trivial_builtin_impls), None))
};
assert!(trivial_builtin_impls.next().is_none());
return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
}
// If there are non-global where-bounds, prefer where-bounds
// (including global ones) over everything else.
let has_non_global_where_bounds = candidates.iter().any(|c| match c.source {
CandidateSource::ParamEnv(idx) => {
let where_bound = goal.param_env.caller_bounds().get(idx);
where_bound.has_bound_vars() || !where_bound.is_global()
let where_bound = goal.param_env.caller_bounds().get(idx).unwrap();
let ty::ClauseKind::Trait(trait_pred) = where_bound.kind().skip_binder() else {
unreachable!("expected trait-bound: {where_bound:?}");
};
if trait_pred.has_bound_vars() || !trait_pred.is_global() {
return true;
}
// We don't consider a trait-bound global if it has a projection bound.
//
// See ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs
// for an example where this is necessary.
for p in goal.param_env.caller_bounds().iter() {
if let ty::ClauseKind::Projection(proj) = p.kind().skip_binder() {
if proj.projection_term.trait_ref(self.cx()) == trait_pred.trait_ref {
return true;
}
}
}
false
}
_ => false,
});

View file

@ -514,13 +514,7 @@ impl<'a> Parser<'a> {
/// Consumes all whitespace characters until the first non-whitespace character
fn ws(&mut self) {
while let Some(&(_, c)) = self.cur.peek() {
if c.is_whitespace() {
self.cur.next();
} else {
break;
}
}
while let Some(_) = self.cur.next_if(|&(_, c)| c.is_whitespace()) {}
}
/// Parses all of a string which is to be considered a "raw literal" in a

View file

@ -189,7 +189,7 @@ pub struct Session {
/// enabled. Makes it so that "please report a bug" is hidden, as ICEs with
/// internal features are wontfix, and they are usually the cause of the ICEs.
/// None signifies that this is not tracked.
pub using_internal_features: Arc<AtomicBool>,
pub using_internal_features: &'static AtomicBool,
/// All commandline args used to invoke the compiler, with @file args fully expanded.
/// This will only be used within debug info, e.g. in the pdb file on windows
@ -966,7 +966,7 @@ pub fn build_session(
sysroot: PathBuf,
cfg_version: &'static str,
ice_file: Option<PathBuf>,
using_internal_features: Arc<AtomicBool>,
using_internal_features: &'static AtomicBool,
expanded_args: Vec<String>,
) -> Session {
// FIXME: This is not general enough to make the warning lint completely override

View file

@ -316,7 +316,7 @@ macro_rules! optional {
#[doc(hidden)]
macro_rules! run_driver {
($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_driver::{Callbacks, Compilation, run_compiler};
use rustc_middle::ty::TyCtxt;
use rustc_interface::interface;
use stable_mir::CompilerError;
@ -347,7 +347,7 @@ macro_rules! run_driver {
/// Runs the compiler against given target and tests it with `test_function`
pub fn run(&mut self) -> Result<C, CompilerError<B>> {
let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> {
RunCompiler::new(&self.args.clone(), self).run();
run_compiler(&self.args.clone(), self);
Ok(())
});
match (compiler_result, self.result.take()) {

View file

@ -167,6 +167,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
exp_span, exp_found.expected, exp_found.found,
);
match self.tcx.coroutine_kind(cause.body_id) {
Some(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen,
_,
)) => (),
None
| Some(
hir::CoroutineKind::Coroutine(_)
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _),
) => return,
}
if let ObligationCauseCode::CompareImplItem { .. } = cause.code() {
return;
}

702
library/alloc/src/bstr.rs Normal file
View file

@ -0,0 +1,702 @@
//! The `ByteStr` and `ByteString` types and trait implementations.
// This could be more fine-grained.
#![cfg(not(no_global_oom_handling))]
use core::borrow::{Borrow, BorrowMut};
#[unstable(feature = "bstr", issue = "134915")]
pub use core::bstr::ByteStr;
use core::bstr::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
use core::cmp::Ordering;
use core::ops::{
Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive,
RangeTo, RangeToInclusive,
};
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
use core::str::FromStr;
use core::{fmt, hash};
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
use crate::borrow::{Cow, ToOwned};
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
use crate::boxed::Box;
#[cfg(not(no_rc))]
use crate::rc::Rc;
use crate::string::String;
#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
use crate::sync::Arc;
use crate::vec::Vec;
/// A wrapper for `Vec<u8>` representing a human-readable string that's conventionally, but not
/// always, UTF-8.
///
/// Unlike `String`, this type permits non-UTF-8 contents, making it suitable for user input,
/// non-native filenames (as `Path` only supports native filenames), and other applications that
/// need to round-trip whatever data the user provides.
///
/// A `ByteString` owns its contents and can grow and shrink, like a `Vec` or `String`. For a
/// borrowed byte string, see [`ByteStr`](../../std/bstr/struct.ByteStr.html).
///
/// `ByteString` implements `Deref` to `&Vec<u8>`, so all methods available on `&Vec<u8>` are
/// available on `ByteString`. Similarly, `ByteString` implements `DerefMut` to `&mut Vec<u8>`,
/// so you can modify a `ByteString` using any method available on `&mut Vec<u8>`.
///
/// The `Debug` and `Display` implementations for `ByteString` are the same as those for `ByteStr`,
/// showing invalid UTF-8 as hex escapes or the Unicode replacement character, respectively.
#[unstable(feature = "bstr", issue = "134915")]
#[repr(transparent)]
#[derive(Clone)]
#[doc(alias = "BString")]
pub struct ByteString(pub Vec<u8>);
impl ByteString {
#[inline]
pub(crate) fn as_bytes(&self) -> &[u8] {
&self.0
}
#[inline]
pub(crate) fn as_bytestr(&self) -> &ByteStr {
ByteStr::new(&self.0)
}
#[inline]
pub(crate) fn as_mut_bytestr(&mut self) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Deref for ByteString {
type Target = Vec<u8>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl DerefMut for ByteString {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[unstable(feature = "deref_pure_trait", issue = "87121")]
unsafe impl DerefPure for ByteString {}
#[unstable(feature = "bstr", issue = "134915")]
impl fmt::Debug for ByteString {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_bytestr(), f)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl fmt::Display for ByteString {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_bytestr(), f)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsRef<[u8]> for ByteString {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsRef<ByteStr> for ByteString {
#[inline]
fn as_ref(&self) -> &ByteStr {
self.as_bytestr()
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsMut<[u8]> for ByteString {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsMut<ByteStr> for ByteString {
#[inline]
fn as_mut(&mut self) -> &mut ByteStr {
self.as_mut_bytestr()
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Borrow<[u8]> for ByteString {
#[inline]
fn borrow(&self) -> &[u8] {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Borrow<ByteStr> for ByteString {
#[inline]
fn borrow(&self) -> &ByteStr {
self.as_bytestr()
}
}
// `impl Borrow<ByteStr> for Vec<u8>` omitted to avoid inference failures
// `impl Borrow<ByteStr> for String` omitted to avoid inference failures
#[unstable(feature = "bstr", issue = "134915")]
impl BorrowMut<[u8]> for ByteString {
#[inline]
fn borrow_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl BorrowMut<ByteStr> for ByteString {
#[inline]
fn borrow_mut(&mut self) -> &mut ByteStr {
self.as_mut_bytestr()
}
}
// `impl BorrowMut<ByteStr> for Vec<u8>` omitted to avoid inference failures
#[unstable(feature = "bstr", issue = "134915")]
impl Default for ByteString {
fn default() -> Self {
ByteString(Vec::new())
}
}
// Omitted due to inference failures
//
// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a, const N: usize> From<&'a [u8; N]> for ByteString {
// #[inline]
// fn from(s: &'a [u8; N]) -> Self {
// ByteString(s.as_slice().to_vec())
// }
// }
//
// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
// #[unstable(feature = "bstr", issue = "134915")]
// impl<const N: usize> From<[u8; N]> for ByteString {
// #[inline]
// fn from(s: [u8; N]) -> Self {
// ByteString(s.as_slice().to_vec())
// }
// }
//
// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a [u8]> for ByteString {
// #[inline]
// fn from(s: &'a [u8]) -> Self {
// ByteString(s.to_vec())
// }
// }
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl From<Vec<u8>> for ByteString {
// #[inline]
// fn from(s: Vec<u8>) -> Self {
// ByteString(s)
// }
// }
#[unstable(feature = "bstr", issue = "134915")]
impl From<ByteString> for Vec<u8> {
#[inline]
fn from(s: ByteString) -> Self {
s.0
}
}
// Omitted due to inference failures
//
// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a str> for ByteString {
// #[inline]
// fn from(s: &'a str) -> Self {
// ByteString(s.as_bytes().to_vec())
// }
// }
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl From<String> for ByteString {
// #[inline]
// fn from(s: String) -> Self {
// ByteString(s.into_bytes())
// }
// }
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> From<&'a ByteStr> for ByteString {
#[inline]
fn from(s: &'a ByteStr) -> Self {
ByteString(s.0.to_vec())
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> From<ByteString> for Cow<'a, ByteStr> {
#[inline]
fn from(s: ByteString) -> Self {
Cow::Owned(s)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> From<&'a ByteString> for Cow<'a, ByteStr> {
#[inline]
fn from(s: &'a ByteString) -> Self {
Cow::Borrowed(s.as_bytestr())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl FromIterator<char> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
ByteString(iter.into_iter().collect::<String>().into_bytes())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl FromIterator<u8> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
ByteString(iter.into_iter().collect())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> FromIterator<&'a str> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
ByteString(iter.into_iter().collect::<String>().into_bytes())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> FromIterator<&'a [u8]> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> Self {
let mut buf = Vec::new();
for b in iter {
buf.extend_from_slice(b);
}
ByteString(buf)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> FromIterator<&'a ByteStr> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = &'a ByteStr>>(iter: T) -> Self {
let mut buf = Vec::new();
for b in iter {
buf.extend_from_slice(&b.0);
}
ByteString(buf)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl FromIterator<ByteString> for ByteString {
#[inline]
fn from_iter<T: IntoIterator<Item = ByteString>>(iter: T) -> Self {
let mut buf = Vec::new();
for mut b in iter {
buf.append(&mut b.0);
}
ByteString(buf)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl FromStr for ByteString {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ByteString(s.as_bytes().to_vec()))
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<usize> for ByteString {
type Output = u8;
#[inline]
fn index(&self, idx: usize) -> &u8 {
&self.0[idx]
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeFull> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, _: RangeFull) -> &ByteStr {
self.as_bytestr()
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<Range<usize>> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, r: Range<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeInclusive<usize>> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeInclusive<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeFrom<usize>> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeFrom<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeTo<usize>> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeTo<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeToInclusive<usize>> for ByteString {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<usize> for ByteString {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut u8 {
&mut self.0[idx]
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeFull> for ByteString {
#[inline]
fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr {
self.as_mut_bytestr()
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<Range<usize>> for ByteString {
#[inline]
fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeInclusive<usize>> for ByteString {
#[inline]
fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeFrom<usize>> for ByteString {
#[inline]
fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeTo<usize>> for ByteString {
#[inline]
fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeToInclusive<usize>> for ByteString {
#[inline]
fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl hash::Hash for ByteString {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Eq for ByteString {}
#[unstable(feature = "bstr", issue = "134915")]
impl PartialEq for ByteString {
#[inline]
fn eq(&self, other: &ByteString) -> bool {
self.0 == other.0
}
}
macro_rules! impl_partial_eq_ord_cow {
($lhs:ty, $rhs:ty) => {
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
let other: &[u8] = (&**other).as_ref();
PartialEq::eq(self.as_bytes(), other)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
let this: &[u8] = (&**self).as_ref();
PartialEq::eq(this, other.as_bytes())
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
let other: &[u8] = (&**other).as_ref();
PartialOrd::partial_cmp(self.as_bytes(), other)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
let this: &[u8] = (&**self).as_ref();
PartialOrd::partial_cmp(this, other.as_bytes())
}
}
};
}
// PartialOrd with `Vec<u8>` omitted to avoid inference failures
impl_partial_eq!(ByteString, Vec<u8>);
// PartialOrd with `[u8]` omitted to avoid inference failures
impl_partial_eq!(ByteString, [u8]);
// PartialOrd with `&[u8]` omitted to avoid inference failures
impl_partial_eq!(ByteString, &[u8]);
// PartialOrd with `String` omitted to avoid inference failures
impl_partial_eq!(ByteString, String);
// PartialOrd with `str` omitted to avoid inference failures
impl_partial_eq!(ByteString, str);
// PartialOrd with `&str` omitted to avoid inference failures
impl_partial_eq!(ByteString, &str);
impl_partial_eq_ord!(ByteString, ByteStr);
impl_partial_eq_ord!(ByteString, &ByteStr);
// PartialOrd with `[u8; N]` omitted to avoid inference failures
impl_partial_eq_n!(ByteString, [u8; N]);
// PartialOrd with `&[u8; N]` omitted to avoid inference failures
impl_partial_eq_n!(ByteString, &[u8; N]);
impl_partial_eq_ord_cow!(ByteString, Cow<'_, ByteStr>);
impl_partial_eq_ord_cow!(ByteString, Cow<'_, str>);
impl_partial_eq_ord_cow!(ByteString, Cow<'_, [u8]>);
#[unstable(feature = "bstr", issue = "134915")]
impl Ord for ByteString {
#[inline]
fn cmp(&self, other: &ByteString) -> Ordering {
Ord::cmp(&self.0, &other.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl PartialOrd for ByteString {
#[inline]
fn partial_cmp(&self, other: &ByteString) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.0, &other.0)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl ToOwned for ByteStr {
type Owned = ByteString;
#[inline]
fn to_owned(&self) -> ByteString {
ByteString(self.0.to_vec())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl TryFrom<ByteString> for String {
type Error = crate::string::FromUtf8Error;
#[inline]
fn try_from(s: ByteString) -> Result<Self, Self::Error> {
String::from_utf8(s.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> TryFrom<&'a ByteString> for &'a str {
type Error = crate::str::Utf8Error;
#[inline]
fn try_from(s: &'a ByteString) -> Result<Self, Self::Error> {
crate::str::from_utf8(s.0.as_slice())
}
}
// Additional impls for `ByteStr` that require types from `alloc`:
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl Clone for Box<ByteStr> {
#[inline]
fn clone(&self) -> Self {
Self::from(Box::<[u8]>::from(&self.0))
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> {
#[inline]
fn from(s: &'a ByteStr) -> Self {
Cow::Borrowed(s)
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl From<Box<[u8]>> for Box<ByteStr> {
#[inline]
fn from(s: Box<[u8]>) -> Box<ByteStr> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Box::from_raw(Box::into_raw(s) as _) }
}
}
#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
#[unstable(feature = "bstr", issue = "134915")]
impl From<Box<ByteStr>> for Box<[u8]> {
#[inline]
fn from(s: Box<ByteStr>) -> Box<[u8]> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Box::from_raw(Box::into_raw(s) as _) }
}
}
#[unstable(feature = "bstr", issue = "134915")]
#[cfg(not(no_rc))]
impl From<Rc<[u8]>> for Rc<ByteStr> {
#[inline]
fn from(s: Rc<[u8]>) -> Rc<ByteStr> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Rc::from_raw(Rc::into_raw(s) as _) }
}
}
#[unstable(feature = "bstr", issue = "134915")]
#[cfg(not(no_rc))]
impl From<Rc<ByteStr>> for Rc<[u8]> {
#[inline]
fn from(s: Rc<ByteStr>) -> Rc<[u8]> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Rc::from_raw(Rc::into_raw(s) as _) }
}
}
#[unstable(feature = "bstr", issue = "134915")]
#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
impl From<Arc<[u8]>> for Arc<ByteStr> {
#[inline]
fn from(s: Arc<[u8]>) -> Arc<ByteStr> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Arc::from_raw(Arc::into_raw(s) as _) }
}
}
#[unstable(feature = "bstr", issue = "134915")]
#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
impl From<Arc<ByteStr>> for Arc<[u8]> {
#[inline]
fn from(s: Arc<ByteStr>) -> Arc<[u8]> {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`.
unsafe { Arc::from_raw(Arc::into_raw(s) as _) }
}
}
// PartialOrd with `Vec<u8>` omitted to avoid inference failures
impl_partial_eq!(ByteStr, Vec<u8>);
// PartialOrd with `String` omitted to avoid inference failures
impl_partial_eq!(ByteStr, String);
impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, ByteStr>);
impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, str>);
impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, [u8]>);
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> TryFrom<&'a ByteStr> for String {
type Error = core::str::Utf8Error;
#[inline]
fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
Ok(core::str::from_utf8(&s.0)?.into())
}
}

View file

@ -102,6 +102,8 @@
#![feature(async_fn_traits)]
#![feature(async_iterator)]
#![feature(box_uninit_write)]
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(clone_to_uninit)]
#![feature(coerce_unsized)]
#![feature(const_eval_select)]
@ -228,6 +230,8 @@ mod boxed {
pub use std::boxed::Box;
}
pub mod borrow;
#[unstable(feature = "bstr", issue = "134915")]
pub mod bstr;
pub mod collections;
#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
pub mod ffi;

581
library/core/src/bstr.rs Normal file
View file

@ -0,0 +1,581 @@
//! The `ByteStr` type and trait implementations.
use crate::borrow::{Borrow, BorrowMut};
use crate::cmp::Ordering;
use crate::ops::{
Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive,
RangeTo, RangeToInclusive,
};
use crate::{fmt, hash};
/// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not
/// always, UTF-8.
///
/// Unlike `&str`, this type permits non-UTF-8 contents, making it suitable for user input,
/// non-native filenames (as `Path` only supports native filenames), and other applications that
/// need to round-trip whatever data the user provides.
///
/// For an owned, growable byte string buffer, use
/// [`ByteString`](../../std/bstr/struct.ByteString.html).
///
/// `ByteStr` implements `Deref` to `[u8]`, so all methods available on `[u8]` are available on
/// `ByteStr`.
///
/// # Representation
///
/// A `&ByteStr` has the same representation as a `&str`. That is, a `&ByteStr` is a wide pointer
/// which includes a pointer to some bytes and a length.
///
/// # Trait implementations
///
/// The `ByteStr` type has a number of trait implementations, and in particular, defines equality
/// and comparisons between `&ByteStr`, `&str`, and `&[u8]`, for convenience.
///
/// The `Debug` implementation for `ByteStr` shows its bytes as a normal string, with invalid UTF-8
/// presented as hex escape sequences.
///
/// The `Display` implementation behaves as if the `ByteStr` were first lossily converted to a
/// `str`, with invalid UTF-8 presented as the Unicode replacement character: <20>
///
#[unstable(feature = "bstr", issue = "134915")]
#[repr(transparent)]
#[doc(alias = "BStr")]
pub struct ByteStr(pub [u8]);
impl ByteStr {
/// Creates a `ByteStr` slice from anything that can be converted to a byte slice.
///
/// This is a zero-cost conversion.
///
/// # Example
///
/// You can create a `ByteStr` from a byte array, a byte slice or a string slice:
///
/// ```
/// # #![feature(bstr)]
/// # use std::bstr::ByteStr;
/// let a = ByteStr::new(b"abc");
/// let b = ByteStr::new(&b"abc"[..]);
/// let c = ByteStr::new("abc");
///
/// assert_eq!(a, b);
/// assert_eq!(a, c);
/// ```
#[inline]
#[unstable(feature = "bstr", issue = "134915")]
pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
ByteStr::from_bytes(bytes.as_ref())
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
#[inline]
pub fn from_bytes(slice: &[u8]) -> &Self {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
// the wrapped type into a reference to the wrapper type.
unsafe { &*(slice as *const [u8] as *const Self) }
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
#[inline]
pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
// SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
// the wrapped type into a reference to the wrapper type.
unsafe { &mut *(slice as *mut [u8] as *mut Self) }
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
#[inline]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Deref for ByteStr {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl DerefMut for ByteStr {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[unstable(feature = "deref_pure_trait", issue = "87121")]
unsafe impl DerefPure for ByteStr {}
#[unstable(feature = "bstr", issue = "134915")]
impl fmt::Debug for ByteStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\"")?;
for chunk in self.utf8_chunks() {
for c in chunk.valid().chars() {
match c {
'\0' => write!(f, "\\0")?,
'\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
_ => write!(f, "{}", c.escape_debug())?,
}
}
write!(f, "{}", chunk.invalid().escape_ascii())?;
}
write!(f, "\"")?;
Ok(())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl fmt::Display for ByteStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for chunk in this.utf8_chunks() {
f.write_str(chunk.valid())?;
if !chunk.invalid().is_empty() {
f.write_str("\u{FFFD}")?;
}
}
Ok(())
}
let Some(align) = f.align() else {
return fmt_nopad(self, f);
};
let nchars: usize = self
.utf8_chunks()
.map(|chunk| chunk.valid().len() + if chunk.invalid().is_empty() { 0 } else { 1 })
.sum();
let padding = f.width().unwrap_or(0).saturating_sub(nchars);
let fill = f.fill();
let (lpad, rpad) = match align {
fmt::Alignment::Left => (0, padding),
fmt::Alignment::Right => (padding, 0),
fmt::Alignment::Center => {
let half = padding / 2;
(half, half + padding % 2)
}
};
for _ in 0..lpad {
write!(f, "{fill}")?;
}
fmt_nopad(self, f)?;
for _ in 0..rpad {
write!(f, "{fill}")?;
}
Ok(())
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsRef<[u8]> for ByteStr {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsRef<ByteStr> for ByteStr {
#[inline]
fn as_ref(&self) -> &ByteStr {
self
}
}
// `impl AsRef<ByteStr> for [u8]` omitted to avoid widespread inference failures
#[unstable(feature = "bstr", issue = "134915")]
impl AsRef<ByteStr> for str {
#[inline]
fn as_ref(&self) -> &ByteStr {
ByteStr::new(self)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl AsMut<[u8]> for ByteStr {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
// `impl AsMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
// `impl Borrow<ByteStr> for [u8]` omitted to avoid widespread inference failures
// `impl Borrow<ByteStr> for str` omitted to avoid widespread inference failures
#[unstable(feature = "bstr", issue = "134915")]
impl Borrow<[u8]> for ByteStr {
#[inline]
fn borrow(&self) -> &[u8] {
&self.0
}
}
// `impl BorrowMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
#[unstable(feature = "bstr", issue = "134915")]
impl BorrowMut<[u8]> for ByteStr {
#[inline]
fn borrow_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> Default for &'a ByteStr {
fn default() -> Self {
ByteStr::from_bytes(b"")
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> Default for &'a mut ByteStr {
fn default() -> Self {
ByteStr::from_bytes_mut(&mut [])
}
}
// Omitted due to inference failures
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a, const N: usize> From<&'a [u8; N]> for &'a ByteStr {
// #[inline]
// fn from(s: &'a [u8; N]) -> Self {
// ByteStr::from_bytes(s)
// }
// }
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a [u8]> for &'a ByteStr {
// #[inline]
// fn from(s: &'a [u8]) -> Self {
// ByteStr::from_bytes(s)
// }
// }
// Omitted due to slice-from-array-issue-113238:
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a ByteStr> for &'a [u8] {
// #[inline]
// fn from(s: &'a ByteStr) -> Self {
// &s.0
// }
// }
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a mut ByteStr> for &'a mut [u8] {
// #[inline]
// fn from(s: &'a mut ByteStr) -> Self {
// &mut s.0
// }
// }
// Omitted due to inference failures
//
// #[unstable(feature = "bstr", issue = "134915")]
// impl<'a> From<&'a str> for &'a ByteStr {
// #[inline]
// fn from(s: &'a str) -> Self {
// ByteStr::from_bytes(s.as_bytes())
// }
// }
#[unstable(feature = "bstr", issue = "134915")]
impl hash::Hash for ByteStr {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<usize> for ByteStr {
type Output = u8;
#[inline]
fn index(&self, idx: usize) -> &u8 {
&self.0[idx]
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeFull> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, _: RangeFull) -> &ByteStr {
self
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<Range<usize>> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, r: Range<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeInclusive<usize>> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeInclusive<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeFrom<usize>> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeFrom<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeTo<usize>> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeTo<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Index<RangeToInclusive<usize>> for ByteStr {
type Output = ByteStr;
#[inline]
fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr {
ByteStr::from_bytes(&self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<usize> for ByteStr {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut u8 {
&mut self.0[idx]
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeFull> for ByteStr {
#[inline]
fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr {
self
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<Range<usize>> for ByteStr {
#[inline]
fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeInclusive<usize>> for ByteStr {
#[inline]
fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeFrom<usize>> for ByteStr {
#[inline]
fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeTo<usize>> for ByteStr {
#[inline]
fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl IndexMut<RangeToInclusive<usize>> for ByteStr {
#[inline]
fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr {
ByteStr::from_bytes_mut(&mut self.0[r])
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl Eq for ByteStr {}
#[unstable(feature = "bstr", issue = "134915")]
impl PartialEq<ByteStr> for ByteStr {
#[inline]
fn eq(&self, other: &ByteStr) -> bool {
&self.0 == &other.0
}
}
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "bstr_internals", issue = "none")]
macro_rules! impl_partial_eq {
($lhs:ty, $rhs:ty) => {
#[allow(unused_lifetimes)]
impl<'a> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
let other: &[u8] = other.as_ref();
PartialEq::eq(self.as_bytes(), other)
}
}
#[allow(unused_lifetimes)]
impl<'a> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
let this: &[u8] = self.as_ref();
PartialEq::eq(this, other.as_bytes())
}
}
};
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
pub use impl_partial_eq;
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "bstr_internals", issue = "none")]
macro_rules! impl_partial_eq_ord {
($lhs:ty, $rhs:ty) => {
$crate::bstr::impl_partial_eq!($lhs, $rhs);
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
let other: &[u8] = other.as_ref();
PartialOrd::partial_cmp(self.as_bytes(), other)
}
}
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
let this: &[u8] = self.as_ref();
PartialOrd::partial_cmp(this, other.as_bytes())
}
}
};
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
pub use impl_partial_eq_ord;
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "bstr_internals", issue = "none")]
macro_rules! impl_partial_eq_n {
($lhs:ty, $rhs:ty) => {
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<const N: usize> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
let other: &[u8] = other.as_ref();
PartialEq::eq(self.as_bytes(), other)
}
}
#[allow(unused_lifetimes)]
#[unstable(feature = "bstr", issue = "134915")]
impl<const N: usize> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
let this: &[u8] = self.as_ref();
PartialEq::eq(this, other.as_bytes())
}
}
};
}
#[doc(hidden)]
#[unstable(feature = "bstr_internals", issue = "none")]
pub use impl_partial_eq_n;
// PartialOrd with `[u8]` omitted to avoid inference failures
impl_partial_eq!(ByteStr, [u8]);
// PartialOrd with `&[u8]` omitted to avoid inference failures
impl_partial_eq!(ByteStr, &[u8]);
// PartialOrd with `str` omitted to avoid inference failures
impl_partial_eq!(ByteStr, str);
// PartialOrd with `&str` omitted to avoid inference failures
impl_partial_eq!(ByteStr, &str);
// PartialOrd with `[u8; N]` omitted to avoid inference failures
impl_partial_eq_n!(ByteStr, [u8; N]);
// PartialOrd with `[u8; N]` omitted to avoid inference failures
impl_partial_eq_n!(ByteStr, &[u8; N]);
#[unstable(feature = "bstr", issue = "134915")]
impl Ord for ByteStr {
#[inline]
fn cmp(&self, other: &ByteStr) -> Ordering {
Ord::cmp(&self.0, &other.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl PartialOrd for ByteStr {
#[inline]
fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
PartialOrd::partial_cmp(&self.0, &other.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> TryFrom<&'a ByteStr> for &'a str {
type Error = crate::str::Utf8Error;
#[inline]
fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
crate::str::from_utf8(&s.0)
}
}
#[unstable(feature = "bstr", issue = "134915")]
impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
type Error = crate::str::Utf8Error;
#[inline]
fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
crate::str::from_utf8_mut(&mut s.0)
}
}

View file

@ -311,6 +311,16 @@ unsafe impl CloneToUninit for crate::ffi::CStr {
}
}
#[unstable(feature = "bstr", issue = "134915")]
unsafe impl CloneToUninit for crate::bstr::ByteStr {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
// SAFETY: ByteStr is a `#[repr(transparent)]` wrapper around `[u8]`
unsafe { self.as_bytes().clone_to_uninit(dst) }
}
}
/// Implementations of `Clone` for primitive types.
///
/// Implementations that cannot be described in Rust

View file

@ -111,6 +111,8 @@
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(bigint_helper_methods)]
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(const_carrying_mul_add)]
#![feature(const_eval_select)]
#![feature(core_intrinsics)]
@ -336,6 +338,8 @@ pub mod ascii;
pub mod asserting;
#[unstable(feature = "async_iterator", issue = "79024")]
pub mod async_iter;
#[unstable(feature = "bstr", issue = "134915")]
pub mod bstr;
pub mod cell;
pub mod char;
pub mod ffi;

View file

@ -0,0 +1,54 @@
#![feature(bstr)]
use core::ByteStr;
#[test]
fn test_debug() {
assert_eq!(
r#""\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff""#,
format!("{:?}", ByteStr::new(b"\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff")),
);
}
#[test]
fn test_display() {
let b1 = ByteStr::new("abc");
let b2 = ByteStr::new(b"\xf0\x28\x8c\xbc");
assert_eq!(&format!("{b1}"), "abc");
assert_eq!(&format!("{b2}"), "<EFBFBD>(<28><>");
assert_eq!(&format!("{b1:<7}!"), "abc !");
assert_eq!(&format!("{b1:>7}!"), " abc!");
assert_eq!(&format!("{b1:^7}!"), " abc !");
assert_eq!(&format!("{b1:^6}!"), " abc !");
assert_eq!(&format!("{b1:-<7}!"), "abc----!");
assert_eq!(&format!("{b1:->7}!"), "----abc!");
assert_eq!(&format!("{b1:-^7}!"), "--abc--!");
assert_eq!(&format!("{b1:-^6}!"), "-abc--!");
assert_eq!(&format!("{b2:<7}!"), "<EFBFBD>(<28><> !");
assert_eq!(&format!("{b2:>7}!"), " <20>(<28><>!");
assert_eq!(&format!("{b2:^7}!"), " <20>(<28><> !");
assert_eq!(&format!("{b2:^6}!"), " <20>(<28><> !");
assert_eq!(&format!("{b2:-<7}!"), "<EFBFBD>(<28><>---!");
assert_eq!(&format!("{b2:->7}!"), "---<2D>(<28><>!");
assert_eq!(&format!("{b2:-^7}!"), "-<2D>(<28><>--!");
assert_eq!(&format!("{b2:-^6}!"), "-<2D>(<28><>-!");
assert_eq!(&format!("{b1:<2}!"), "abc!");
assert_eq!(&format!("{b1:>2}!"), "abc!");
assert_eq!(&format!("{b1:^2}!"), "abc!");
assert_eq!(&format!("{b1:-<2}!"), "abc!");
assert_eq!(&format!("{b1:->2}!"), "abc!");
assert_eq!(&format!("{b1:-^2}!"), "abc!");
assert_eq!(&format!("{b2:<3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:>3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:^3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:^2}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:-<3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:->3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:-^3}!"), "<EFBFBD>(<28><>!");
assert_eq!(&format!("{b2:-^2}!"), "<EFBFBD>(<28><>!");
}

4
library/std/src/bstr.rs Normal file
View file

@ -0,0 +1,4 @@
//! The `ByteStr` and `ByteString` types and trait implementations.
#[unstable(feature = "bstr", issue = "134915")]
pub use alloc::bstr::{ByteStr, ByteString};

View file

@ -320,6 +320,8 @@
// Library features (core):
// tidy-alphabetical-start
#![feature(array_chunks)]
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(c_str_module)]
#![feature(char_internals)]
#![feature(clone_to_uninit)]
@ -581,6 +583,8 @@ pub mod f64;
pub mod thread;
pub mod ascii;
pub mod backtrace;
#[unstable(feature = "bstr", issue = "134915")]
pub mod bstr;
pub mod collections;
pub mod env;
pub mod error;

View file

@ -18,8 +18,8 @@ use std::path::Path;
use rustc_ast_pretty::pprust::item_to_string;
use rustc_data_structures::sync::Lrc;
use rustc_driver::{Compilation, RunCompiler};
use rustc_interface::interface::Compiler;
use rustc_driver::{Compilation, run_compiler};
use rustc_interface::interface::{Compiler, Config};
use rustc_middle::ty::TyCtxt;
struct MyFileLoader;
@ -51,6 +51,10 @@ fn main() {
struct MyCallbacks;
impl rustc_driver::Callbacks for MyCallbacks {
fn config(&mut self, config: &mut Config) {
config.file_loader = Some(Box::new(MyFileLoader));
}
fn after_crate_root_parsing(
&mut self,
_compiler: &Compiler,
@ -83,10 +87,5 @@ impl rustc_driver::Callbacks for MyCallbacks {
}
fn main() {
match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) {
mut compiler => {
compiler.set_file_loader(Some(Box::new(MyFileLoader)));
compiler.run();
}
}
run_compiler(&["main.rs".to_string()], &mut MyCallbacks);
}

View file

@ -18,8 +18,8 @@ use std::path::Path;
use rustc_ast_pretty::pprust::item_to_string;
use rustc_data_structures::sync::Lrc;
use rustc_driver::{Compilation, RunCompiler};
use rustc_interface::interface::Compiler;
use rustc_driver::{Compilation, run_compiler};
use rustc_interface::interface::{Compiler, Config};
use rustc_middle::ty::TyCtxt;
struct MyFileLoader;
@ -51,6 +51,10 @@ fn main() {
struct MyCallbacks;
impl rustc_driver::Callbacks for MyCallbacks {
fn config(&mut self, config: &mut Config) {
config.file_loader = Some(Box::new(MyFileLoader));
}
fn after_crate_root_parsing(
&mut self,
_compiler: &Compiler,
@ -90,10 +94,5 @@ impl rustc_driver::Callbacks for MyCallbacks {
}
fn main() {
match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) {
mut compiler => {
compiler.set_file_loader(Some(Box::new(MyFileLoader)));
compiler.run();
}
}
run_compiler(&["main.rs".to_string()], &mut MyCallbacks);
}

View file

@ -6,7 +6,7 @@ The [`rustc_driver`] is essentially `rustc`'s `main` function.
It acts as the glue for running the various phases of the compiler in the correct order,
using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended.
The main entry point of [`rustc_driver`] is [`rustc_driver::RunCompiler`][rd_rc].
The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc].
This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`][cb] and a couple of other optional options.
[`Callbacks`][cb] is a `trait` that allows for custom compiler configuration,
as well as allowing custom code to run after different phases of the compilation.
@ -40,7 +40,7 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc]
[cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html
[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-interface-example.rs
[i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html
[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/struct.RunCompiler.html
[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html
[rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html
[stupid-stats]: https://github.com/nrc/stupid-stats
[`nightly-rustc`]: https://doc.rust-lang.org/nightly/nightly-rustc/

View file

@ -1,10 +1,10 @@
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, LazyLock};
use std::sync::LazyLock;
use std::{io, mem};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordSet;
use rustc_driver::USING_INTERNAL_FEATURES;
use rustc_errors::TerminalUrl;
use rustc_errors::codes::*;
use rustc_errors::emitter::{
@ -221,7 +221,6 @@ pub(crate) fn create_config(
..
}: RustdocOptions,
RenderOptions { document_private, .. }: &RenderOptions,
using_internal_features: Arc<AtomicBool>,
) -> rustc_interface::Config {
// Add the doc cfg into the doc build.
cfgs.push("doc".to_string());
@ -316,7 +315,7 @@ pub(crate) fn create_config(
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
ice_file: None,
using_internal_features,
using_internal_features: &USING_INTERNAL_FEATURES,
expanded_args,
}
}

View file

@ -193,7 +193,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
ice_file: None,
using_internal_features: Arc::default(),
using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,
expanded_args: options.expanded_args.clone(),
};

View file

@ -74,8 +74,6 @@ extern crate tikv_jemalloc_sys as jemalloc_sys;
use std::env::{self, VarError};
use std::io::{self, IsTerminal};
use std::process;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use rustc_errors::DiagCtxtHandle;
use rustc_interface::interface;
@ -159,7 +157,7 @@ pub fn main() {
let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
let using_internal_features = rustc_driver::install_ice_hook(
rustc_driver::install_ice_hook(
"https://github.com/rust-lang/rust/issues/new\
?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md",
|_| (),
@ -180,7 +178,7 @@ pub fn main() {
let exit_code = rustc_driver::catch_with_exit_code(|| {
let at_args = rustc_driver::args::raw_args(&early_dcx)?;
main_args(&mut early_dcx, &at_args, using_internal_features);
main_args(&mut early_dcx, &at_args);
Ok(())
});
process::exit(exit_code);
@ -769,11 +767,7 @@ fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> {
Ok(())
}
fn main_args(
early_dcx: &mut EarlyDiagCtxt,
at_args: &[String],
using_internal_features: Arc<AtomicBool>,
) {
fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
// Throw away the first argument, the name of the binary.
// In case of at_args being empty, as might be the case by
// passing empty argument array to execve under some platforms,
@ -826,8 +820,7 @@ fn main_args(
(false, Some(md_input)) => {
let md_input = md_input.to_owned();
let edition = options.edition;
let config =
core::create_config(input, options, &render_options, using_internal_features);
let config = core::create_config(input, options, &render_options);
// `markdown::render` can invoke `doctest::make_test`, which
// requires session globals and a thread pool, so we use
@ -860,7 +853,7 @@ fn main_args(
let scrape_examples_options = options.scrape_examples_options.clone();
let bin_crate = options.bin_crate;
let config = core::create_config(input, options, &render_options, using_internal_features);
let config = core::create_config(input, options, &render_options);
let registered_lints = config.register_lints.is_some();

View file

@ -186,7 +186,7 @@ pub fn main() {
rustc_driver::init_rustc_env_logger(&early_dcx);
let using_internal_features = rustc_driver::install_ice_hook(BUG_REPORT_URL, |dcx| {
rustc_driver::install_ice_hook(BUG_REPORT_URL, |dcx| {
// FIXME: this macro calls unwrap internally but is called in a panicking context! It's not
// as simple as moving the call from the hook to main, because `install_ice_hook` doesn't
// accept a generic closure.
@ -236,7 +236,7 @@ pub fn main() {
let mut args: Vec<String> = orig_args.clone();
pass_sysroot_env_if_given(&mut args, sys_root_env);
rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
rustc_driver::run_compiler(&args, &mut DefaultCallbacks);
return Ok(());
}
@ -295,13 +295,9 @@ pub fn main() {
let clippy_enabled = !cap_lints_allow && relevant_package && !info_query;
if clippy_enabled {
args.extend(clippy_args);
rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var })
.set_using_internal_features(using_internal_features)
.run();
rustc_driver::run_compiler(&args, &mut ClippyCallbacks { clippy_args_var });
} else {
rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var })
.set_using_internal_features(using_internal_features)
.run();
rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var });
}
Ok(())
}))

View file

@ -50,6 +50,29 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
("alloc/slice/trait.Concat.html", &["#method.concat"]),
("alloc/slice/index.html", &["#method.concat", "#method.join"]),
("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]),
("alloc/bstr/struct.ByteStr.html", &[
"#method.to_ascii_uppercase",
"#method.to_ascii_lowercase",
"core/slice::sort_by_key",
"core\\slice::sort_by_key",
"#method.sort_by_cached_key",
"#method.sort_by_key"
]),
("alloc/bstr/struct.ByteString.html", &[
"#method.to_ascii_uppercase",
"#method.to_ascii_lowercase",
"core/slice::sort_by_key",
"core\\slice::sort_by_key",
"#method.sort_by_cached_key",
"#method.sort_by_key"
]),
("core/bstr/struct.ByteStr.html", &[
"#method.to_ascii_uppercase",
"#method.to_ascii_lowercase",
"core/bstr/slice::sort_by_key",
"core\\bstr\\slice::sort_by_key",
"#method.sort_by_cached_key"
]),
("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]),
("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
"core/slice::sort_by_key", "core\\slice::sort_by_key",

View file

@ -30,7 +30,7 @@ use std::ops::Range;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::atomic::{AtomicI32, Ordering};
use std::sync::{Arc, Once};
use std::sync::Once;
use miri::{
BacktraceStyle, BorrowTrackerMethod, MiriConfig, MiriEntryFnType,ProvenanceMode, RetagFields, ValidationMode,
@ -370,13 +370,10 @@ fn init_late_loggers(early_dcx: &EarlyDiagCtxt, tcx: TyCtxt<'_>) {
fn run_compiler_and_exit(
args: &[String],
callbacks: &mut (dyn rustc_driver::Callbacks + Send),
using_internal_features: Arc<std::sync::atomic::AtomicBool>,
) -> ! {
// Invoke compiler, and handle return code.
let exit_code = rustc_driver::catch_with_exit_code(move || {
rustc_driver::RunCompiler::new(args, callbacks)
.set_using_internal_features(using_internal_features)
.run();
rustc_driver::run_compiler(args, callbacks);
Ok(())
});
std::process::exit(exit_code)
@ -467,8 +464,7 @@ fn main() {
// If the environment asks us to actually be rustc, then do that.
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
// Earliest rustc setup.
let using_internal_features =
rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
rustc_driver::init_rustc_env_logger(&early_dcx);
let target_crate = if crate_kind == "target" {
@ -492,16 +488,11 @@ fn main() {
}
// We cannot use `rustc_driver::main` as we want it to use `args` as the CLI arguments.
run_compiler_and_exit(
&args,
&mut MiriBeRustCompilerCalls { target_crate },
using_internal_features,
)
run_compiler_and_exit(&args, &mut MiriBeRustCompilerCalls { target_crate })
}
// Add an ICE bug report hook.
let using_internal_features =
rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ());
rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ());
// Init loggers the Miri way.
init_early_loggers(&early_dcx);
@ -735,9 +726,5 @@ fn main() {
debug!("rustc arguments: {:?}", rustc_args);
debug!("crate arguments: {:?}", miri_config.args);
run_compiler_and_exit(
&rustc_args,
&mut MiriCompilerCalls::new(miri_config, many_seeds),
using_internal_features,
)
run_compiler_and_exit(&rustc_args, &mut MiriCompilerCalls::new(miri_config, many_seeds))
}

View file

@ -25,7 +25,7 @@ fn main() {
let mut count = 1;
let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
rustc_driver::catch_fatal_errors(|| -> interface::Result<()> {
rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run();
rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count });
Ok(())
})
.ok();

View file

@ -47,7 +47,7 @@ fn main() {
rustc_args.push("-Zpolonius".to_owned());
let mut callbacks = CompilerCalls::default();
// Call the Rust compiler with our callbacks.
rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run();
rustc_driver::run_compiler(&rustc_args, &mut callbacks);
Ok(())
});
std::process::exit(exit_code);

View file

@ -72,7 +72,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path
override_queries: None,
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
using_internal_features: std::sync::Arc::default(),
using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,
expanded_args: Default::default(),
};

View file

@ -40,14 +40,14 @@ LL | type X = std::ops::Deref::Target;
|
help: use fully-qualified syntax
|
LL | type X = <ByteStr as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | type X = <ByteString as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | type X = <CString as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | type X = <IoSlice<'_> as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | type X = <IoSliceMut<'_> as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | type X = <OsString as Deref>::Target;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
and N other candidates
error: aborting due to 5 previous errors

View file

@ -30,7 +30,6 @@ LL | fun(one(), two());
| | expected all arguments to be this future type because they need to match the type of this parameter
| arguments to this function are incorrect
|
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
note: function defined here
--> $DIR/coroutine-desc.rs:7:4

View file

@ -6,20 +6,11 @@ LL | take_u32(x)
| |
| arguments to this function are incorrect
|
note: calling an async function returns a future
--> $DIR/dont-suggest-missing-await.rs:14:18
|
LL | take_u32(x)
| ^
note: function defined here
--> $DIR/dont-suggest-missing-await.rs:5:4
|
LL | fn take_u32(x: u32) {}
| ^^^^^^^^ ------
help: consider `await`ing on the `Future`
|
LL | take_u32(x.await)
| ++++++
error: aborting due to 1 previous error

View file

@ -32,13 +32,13 @@ LL | [5; Self::HOST_SIZE] == [6; 0]
= help: the following other types implement trait `PartialEq<Rhs>`:
`&[T]` implements `PartialEq<Vec<U, A>>`
`&[T]` implements `PartialEq<[U; N]>`
`&[u8; N]` implements `PartialEq<ByteStr>`
`&[u8; N]` implements `PartialEq<ByteString>`
`&[u8]` implements `PartialEq<ByteStr>`
`&[u8]` implements `PartialEq<ByteString>`
`&mut [T]` implements `PartialEq<Vec<U, A>>`
`&mut [T]` implements `PartialEq<[U; N]>`
`[T; N]` implements `PartialEq<&[U]>`
`[T; N]` implements `PartialEq<&mut [U]>`
`[T; N]` implements `PartialEq<[U; N]>`
`[T; N]` implements `PartialEq<[U]>`
and 3 others
and 11 others
error: aborting due to 4 previous errors

View file

@ -14,20 +14,11 @@ LL | convert_result(foo())
| |
| arguments to this function are incorrect
|
note: calling an async function returns a future
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
| ^^^^^
note: function defined here
--> $DIR/issue-102605.rs:7:4
|
LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
| ^^^^^^^^^^^^^^ ---------------
help: consider `await`ing on the `Future`
|
LL | convert_result(foo().await)
| ++++++
help: try wrapping the expression in `Err`
|
LL | convert_result(Err(foo()))

View file

@ -6,11 +6,14 @@ LL | if String::from("a") == "a".try_into().unwrap() {}
| |
| type must be known at this point
|
= note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate:
- impl PartialEq for String;
- impl<'a, 'b> PartialEq<&'a str> for String;
- impl<'a, 'b> PartialEq<Cow<'a, str>> for String;
- impl<'a, 'b> PartialEq<str> for String;
= note: cannot satisfy `String: PartialEq<_>`
= help: the following types implement trait `PartialEq<Rhs>`:
`String` implements `PartialEq<&str>`
`String` implements `PartialEq<ByteStr>`
`String` implements `PartialEq<ByteString>`
`String` implements `PartialEq<Cow<'_, str>>`
`String` implements `PartialEq<str>`
`String` implements `PartialEq`
help: try using a fully qualified path to specify the expected types
|
LL | if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}

View file

@ -15,6 +15,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -41,6 +42,7 @@ LL | |x| String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -57,6 +59,7 @@ LL | let _ = "x".as_ref();
| ^ ------ type must be known at this point
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -83,6 +86,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -109,6 +113,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -135,6 +140,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -161,6 +167,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -187,6 +194,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;
@ -213,6 +221,7 @@ LL | String::from("x".as_ref());
| ^^^^^^
|
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
- impl AsRef<ByteStr> for str;
- impl AsRef<OsStr> for str;
- impl AsRef<Path> for str;
- impl AsRef<[u8]> for str;

View file

@ -0,0 +1,21 @@
//@ compile-flags: -Znext-solver
//@ check-pass
// `(): Trait` is a global where-bound with a projection bound.
// This previously resulted in ambiguity as we considered both
// the impl and the where-bound while normalizing.
trait Trait {
type Assoc;
}
impl Trait for () {
type Assoc = &'static ();
}
fn foo<'a>(x: <() as Trait>::Assoc)
where
(): Trait<Assoc = &'a ()>,
{
}
fn main() {}