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:
commit
1c9837df1d
42 changed files with 1609 additions and 251 deletions
|
|
@ -4260,7 +4260,6 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_type_ir",
|
||||
"rustc_type_ir_macros",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
47
compiler/rustc_middle/src/query/arena_cached.rs
Normal file
47
compiler/rustc_middle/src/query/arena_cached.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>)
|
||||
()
|
||||
),)*
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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
702
library/alloc/src/bstr.rs
Normal 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())
|
||||
}
|
||||
}
|
||||
|
|
@ -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
581
library/core/src/bstr.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
54
library/core/tests/bstr.rs
Normal file
54
library/core/tests/bstr.rs
Normal 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
4
library/std/src/bstr.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//! The `ByteStr` and `ByteString` types and trait implementations.
|
||||
|
||||
#[unstable(feature = "bstr", issue = "134915")]
|
||||
pub use alloc::bstr::{ByteStr, ByteString};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue