Merge from rustc
This commit is contained in:
commit
b58cbe2361
@ -118,8 +118,8 @@ pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
|
||||
GlobalAsmConfig {
|
||||
assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
|
||||
target: match &tcx.sess.opts.target_triple {
|
||||
rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(),
|
||||
rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => {
|
||||
rustc_target::spec::TargetTuple::TargetTuple(triple) => triple.clone(),
|
||||
rustc_target::spec::TargetTuple::TargetJson { path_for_rustdoc, .. } => {
|
||||
path_for_rustdoc.to_str().unwrap().to_owned()
|
||||
}
|
||||
},
|
||||
|
@ -146,7 +146,7 @@ fn codegen_static(&self, def_id: DefId) {
|
||||
|
||||
// Wasm statics with custom link sections get special treatment as they
|
||||
// go into custom sections of the wasm executable.
|
||||
if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
|
||||
if self.tcx.sess.opts.target_triple.tuple().starts_with("wasm32") {
|
||||
if let Some(_section) = attrs.link_section {
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -946,7 +946,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data:
|
||||
}
|
||||
|
||||
fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
|
||||
let triple = cgcx.opts.target_triple.triple();
|
||||
let triple = cgcx.opts.target_triple.tuple();
|
||||
triple.contains("-ios")
|
||||
|| triple.contains("-darwin")
|
||||
|| triple.contains("-tvos")
|
||||
@ -955,7 +955,7 @@ fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
|
||||
}
|
||||
|
||||
fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
|
||||
cgcx.opts.target_triple.triple().contains("-aix")
|
||||
cgcx.opts.target_triple.tuple().contains("-aix")
|
||||
}
|
||||
|
||||
pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr {
|
||||
@ -1031,7 +1031,7 @@ unsafe fn embed_bitcode(
|
||||
let is_aix = target_is_aix(cgcx);
|
||||
let is_apple = target_is_apple(cgcx);
|
||||
unsafe {
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.tuple().starts_with("wasm") {
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
|
@ -997,7 +997,7 @@ fn is_illegal_instruction(_status: &ExitStatus) -> bool {
|
||||
{
|
||||
let is_vs_installed = windows_registry::find_vs_version().is_ok();
|
||||
let has_linker = windows_registry::find_tool(
|
||||
sess.opts.target_triple.triple(),
|
||||
sess.opts.target_triple.tuple(),
|
||||
"link.exe",
|
||||
)
|
||||
.is_some();
|
||||
@ -1323,10 +1323,8 @@ fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
|
||||
} else {
|
||||
let default_sysroot =
|
||||
filesearch::get_or_default_sysroot().expect("Failed finding sysroot");
|
||||
let default_tlib = filesearch::make_target_lib_path(
|
||||
&default_sysroot,
|
||||
sess.opts.target_triple.triple(),
|
||||
);
|
||||
let default_tlib =
|
||||
filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.tuple());
|
||||
default_tlib
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ pub(crate) fn get_linker<'a>(
|
||||
self_contained: bool,
|
||||
target_cpu: &'a str,
|
||||
) -> Box<dyn Linker + 'a> {
|
||||
let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.triple(), "link.exe");
|
||||
let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.tuple(), "link.exe");
|
||||
|
||||
// If our linker looks like a batch script on Windows then to execute this
|
||||
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
|
||||
|
@ -1,9 +1,6 @@
|
||||
const_eval_address_space_full =
|
||||
there are no more free addresses in the address space
|
||||
|
||||
const_eval_align_offset_invalid_align =
|
||||
`align_offset` called with non-power-of-two align: {$target_align}
|
||||
|
||||
const_eval_alignment_check_failed =
|
||||
{$msg ->
|
||||
[AccessedPtr] accessing memory
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
|
||||
@ -9,7 +8,7 @@
|
||||
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
|
||||
use rustc_middle::mir::AssertMessage;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_span::Span;
|
||||
@ -23,9 +22,9 @@
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::interpret::{
|
||||
self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy,
|
||||
InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, RangeSet, Scalar,
|
||||
StackPopCleanup, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub,
|
||||
throw_ub_custom, throw_unsup, throw_unsup_format,
|
||||
InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine,
|
||||
interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup,
|
||||
throw_unsup_format,
|
||||
};
|
||||
|
||||
/// When hitting this many interpreted terminators we emit a deny by default lint
|
||||
@ -227,8 +226,8 @@ fn hook_special_const_fn(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[FnArg<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_dest: &MPlaceTy<'tcx>,
|
||||
_ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
|
||||
let def_id = instance.def_id();
|
||||
|
||||
@ -260,85 +259,10 @@ fn hook_special_const_fn(
|
||||
);
|
||||
|
||||
return interp_ok(Some(new_instance));
|
||||
} else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
|
||||
let args = self.copy_fn_args(args);
|
||||
// For align_offset, we replace the function call if the pointer has no address.
|
||||
match self.align_offset(instance, &args, dest, ret)? {
|
||||
ControlFlow::Continue(()) => return interp_ok(Some(instance)),
|
||||
ControlFlow::Break(()) => return interp_ok(None),
|
||||
}
|
||||
}
|
||||
interp_ok(Some(instance))
|
||||
}
|
||||
|
||||
/// `align_offset(ptr, target_align)` needs special handling in const eval, because the pointer
|
||||
/// may not have an address.
|
||||
///
|
||||
/// If `ptr` does have a known address, then we return `Continue(())` and the function call should
|
||||
/// proceed as normal.
|
||||
///
|
||||
/// If `ptr` doesn't have an address, but its underlying allocation's alignment is at most
|
||||
/// `target_align`, then we call the function again with an dummy address relative to the
|
||||
/// allocation.
|
||||
///
|
||||
/// If `ptr` doesn't have an address and `target_align` is stricter than the underlying
|
||||
/// allocation's alignment, then we return `usize::MAX` immediately.
|
||||
fn align_offset(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx, ControlFlow<()>> {
|
||||
assert_eq!(args.len(), 2);
|
||||
|
||||
let ptr = self.read_pointer(&args[0])?;
|
||||
let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
|
||||
|
||||
if !target_align.is_power_of_two() {
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_align_offset_invalid_align,
|
||||
target_align = target_align,
|
||||
);
|
||||
}
|
||||
|
||||
match self.ptr_try_get_alloc_id(ptr, 0) {
|
||||
Ok((alloc_id, offset, _extra)) => {
|
||||
let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
|
||||
|
||||
if target_align <= alloc_align.bytes() {
|
||||
// Extract the address relative to the allocation base that is definitely
|
||||
// sufficiently aligned and call `align_offset` again.
|
||||
let addr = ImmTy::from_uint(offset.bytes(), args[0].layout).into();
|
||||
let align = ImmTy::from_uint(target_align, args[1].layout).into();
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
|
||||
|
||||
// Push the stack frame with our own adjusted arguments.
|
||||
self.init_stack_frame(
|
||||
instance,
|
||||
self.load_mir(instance.def, None)?,
|
||||
fn_abi,
|
||||
&[FnArg::Copy(addr), FnArg::Copy(align)],
|
||||
/* with_caller_location = */ false,
|
||||
dest,
|
||||
StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Unreachable },
|
||||
)?;
|
||||
interp_ok(ControlFlow::Break(()))
|
||||
} else {
|
||||
// Not alignable in const, return `usize::MAX`.
|
||||
let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
|
||||
self.write_scalar(usize_max, dest)?;
|
||||
self.return_to_block(ret)?;
|
||||
interp_ok(ControlFlow::Break(()))
|
||||
}
|
||||
}
|
||||
Err(_addr) => {
|
||||
// The pointer has an address, continue with function call.
|
||||
interp_ok(ControlFlow::Continue(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See documentation on the `ptr_guaranteed_cmp` intrinsic.
|
||||
fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
|
||||
interp_ok(match (a, b) {
|
||||
|
@ -62,7 +62,7 @@
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::source_map::FileLoader;
|
||||
use rustc_target::json::ToJson;
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use rustc_target::spec::{Target, TargetTuple};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
|
||||
@ -731,6 +731,7 @@ fn print_crate_info(
|
||||
targets.sort_unstable();
|
||||
println_info!("{}", targets.join("\n"));
|
||||
}
|
||||
HostTuple => println_info!("{}", rustc_session::config::host_tuple()),
|
||||
Sysroot => println_info!("{}", sess.sysroot.display()),
|
||||
TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()),
|
||||
TargetSpec => {
|
||||
@ -739,7 +740,7 @@ fn print_crate_info(
|
||||
AllTargetSpecs => {
|
||||
let mut targets = BTreeMap::new();
|
||||
for name in rustc_target::spec::TARGETS {
|
||||
let triple = TargetTriple::from_triple(name);
|
||||
let triple = TargetTuple::from_tuple(name);
|
||||
let target = Target::expect_builtin(&triple);
|
||||
targets.insert(name, target.to_json());
|
||||
}
|
||||
@ -918,7 +919,7 @@ pub fn version_at_macro_invocation(
|
||||
safe_println!("binary: {binary}");
|
||||
safe_println!("commit-hash: {commit_hash}");
|
||||
safe_println!("commit-date: {commit_date}");
|
||||
safe_println!("host: {}", config::host_triple());
|
||||
safe_println!("host: {}", config::host_tuple());
|
||||
safe_println!("release: {release}");
|
||||
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
@ -1495,7 +1496,7 @@ fn report_ice(
|
||||
}
|
||||
|
||||
let version = util::version_str!().unwrap_or("unknown_version");
|
||||
let triple = config::host_triple();
|
||||
let tuple = config::host_tuple();
|
||||
|
||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
@ -1505,7 +1506,7 @@ fn report_ice(
|
||||
Ok(mut file) => {
|
||||
dcx.emit_note(session_diagnostics::IcePath { path: path.clone() });
|
||||
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||
let _ = write!(file, "\n\nrustc version: {version}\nplatform: {triple}");
|
||||
let _ = write!(file, "\n\nrustc version: {version}\nplatform: {tuple}");
|
||||
}
|
||||
Some(file)
|
||||
}
|
||||
@ -1518,12 +1519,12 @@ fn report_ice(
|
||||
.map(PathBuf::from)
|
||||
.map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }),
|
||||
});
|
||||
dcx.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||
dcx.emit_note(session_diagnostics::IceVersion { version, triple: tuple });
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dcx.emit_note(session_diagnostics::IceVersion { version, triple });
|
||||
dcx.emit_note(session_diagnostics::IceVersion { version, triple: tuple });
|
||||
None
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc_span::Span;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
|
||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTuple};
|
||||
use rustc_type_ir::{ClosureKind, FloatTy};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
@ -89,7 +89,7 @@ fn into_diag_arg(self) -> DiagArgValue {
|
||||
MacroRulesNormalizedIdent,
|
||||
ParseIntError,
|
||||
StackProtector,
|
||||
&TargetTriple,
|
||||
&TargetTuple,
|
||||
SplitDebuginfo,
|
||||
ExitStatus,
|
||||
ErrCode,
|
||||
|
@ -348,9 +348,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
|
||||
|
||||
MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
|
||||
|
||||
/// Align offset for stride != 1; must not panic.
|
||||
AlignOffset, sym::align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;
|
||||
|
||||
Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;
|
||||
|
@ -493,7 +493,7 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
|
||||
"we would appreciate a joke overview: \
|
||||
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
|
||||
);
|
||||
diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),));
|
||||
diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_tuple(),));
|
||||
if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() {
|
||||
diag.note(format!("compiler flags: {}", flags.join(" ")));
|
||||
if excluded_cargo_defaults {
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc_metadata::{DylibError, load_symbol_from_dylib};
|
||||
use rustc_middle::ty::CurrentGcx;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_triple};
|
||||
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_tuple};
|
||||
use rustc_session::filesearch::sysroot_candidates;
|
||||
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
|
||||
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
|
||||
@ -310,7 +310,7 @@ fn get_codegen_sysroot(
|
||||
"cannot load the default codegen backend twice"
|
||||
);
|
||||
|
||||
let target = host_triple();
|
||||
let target = host_tuple();
|
||||
let sysroot_candidates = sysroot_candidates();
|
||||
|
||||
let sysroot = iter::once(sysroot)
|
||||
|
@ -30,7 +30,7 @@
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_target::spec::{PanicStrategy, Target, TargetTriple};
|
||||
use rustc_target::spec::{PanicStrategy, Target, TargetTuple};
|
||||
use tracing::{debug, info, trace};
|
||||
|
||||
use crate::errors;
|
||||
@ -506,7 +506,7 @@ fn load_proc_macro<'b>(
|
||||
locator.reset();
|
||||
locator.is_proc_macro = true;
|
||||
locator.target = &self.sess.host;
|
||||
locator.triple = TargetTriple::from_triple(config::host_triple());
|
||||
locator.tuple = TargetTuple::from_tuple(config::host_tuple());
|
||||
locator.filesearch = self.sess.host_filesearch(path_kind);
|
||||
|
||||
let Some(host_result) = self.load(locator)? else {
|
||||
@ -635,7 +635,7 @@ fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, Cra
|
||||
// FIXME: why is this condition necessary? It was adding in #33625 but I
|
||||
// don't know why and the original author doesn't remember ...
|
||||
let can_reuse_cratenum =
|
||||
locator.triple == self.sess.opts.target_triple || locator.is_proc_macro;
|
||||
locator.tuple == self.sess.opts.target_triple || locator.is_proc_macro;
|
||||
Ok(Some(if can_reuse_cratenum {
|
||||
let mut result = LoadResult::Loaded(library);
|
||||
for (cnum, data) in self.cstore.iter_crate_data() {
|
||||
|
@ -5,7 +5,7 @@
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTuple};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::locator::CrateFlavor;
|
||||
@ -630,7 +630,7 @@ pub struct CannotFindCrate {
|
||||
pub current_crate: String,
|
||||
pub is_nightly_build: bool,
|
||||
pub profiler_runtime: Symbol,
|
||||
pub locator_triple: TargetTriple,
|
||||
pub locator_triple: TargetTuple,
|
||||
pub is_ui_testing: bool,
|
||||
}
|
||||
|
||||
@ -641,7 +641,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
||||
diag.arg("crate_name", self.crate_name);
|
||||
diag.arg("current_crate", self.current_crate);
|
||||
diag.arg("add_info", self.add_info);
|
||||
diag.arg("locator_triple", self.locator_triple.triple());
|
||||
diag.arg("locator_triple", self.locator_triple.tuple());
|
||||
diag.code(E0463);
|
||||
diag.span(self.span);
|
||||
if self.crate_name == sym::std || self.crate_name == sym::core {
|
||||
|
@ -231,7 +231,7 @@
|
||||
use rustc_session::utils::CanonicalizedPath;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use rustc_target::spec::{Target, TargetTuple};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::creader::{Library, MetadataLoader};
|
||||
@ -252,7 +252,7 @@ pub(crate) struct CrateLocator<'a> {
|
||||
pub hash: Option<Svh>,
|
||||
extra_filename: Option<&'a str>,
|
||||
pub target: &'a Target,
|
||||
pub triple: TargetTriple,
|
||||
pub tuple: TargetTuple,
|
||||
pub filesearch: FileSearch<'a>,
|
||||
pub is_proc_macro: bool,
|
||||
|
||||
@ -338,7 +338,7 @@ pub(crate) fn new(
|
||||
hash,
|
||||
extra_filename,
|
||||
target: &sess.target,
|
||||
triple: sess.opts.target_triple.clone(),
|
||||
tuple: sess.opts.target_triple.clone(),
|
||||
filesearch: sess.target_filesearch(path_kind),
|
||||
is_proc_macro: false,
|
||||
crate_rejections: CrateRejections::default(),
|
||||
@ -677,8 +677,8 @@ fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<S
|
||||
return None;
|
||||
}
|
||||
|
||||
if header.triple != self.triple {
|
||||
info!("Rejecting via crate triple: expected {} got {}", self.triple, header.triple);
|
||||
if header.triple != self.tuple {
|
||||
info!("Rejecting via crate triple: expected {} got {}", self.tuple, header.triple);
|
||||
self.crate_rejections.via_triple.push(CrateMismatch {
|
||||
path: libpath.to_path_buf(),
|
||||
got: header.triple.to_string(),
|
||||
@ -766,7 +766,7 @@ pub(crate) fn into_error(self, root: Option<CratePaths>) -> CrateError {
|
||||
CrateError::LocatorCombined(Box::new(CombinedLocatorError {
|
||||
crate_name: self.crate_name,
|
||||
root,
|
||||
triple: self.triple,
|
||||
triple: self.tuple,
|
||||
dll_prefix: self.target.dll_prefix.to_string(),
|
||||
dll_suffix: self.target.dll_suffix.to_string(),
|
||||
crate_rejections: self.crate_rejections,
|
||||
@ -909,7 +909,7 @@ struct CrateRejections {
|
||||
pub(crate) struct CombinedLocatorError {
|
||||
crate_name: Symbol,
|
||||
root: Option<CratePaths>,
|
||||
triple: TargetTriple,
|
||||
triple: TargetTuple,
|
||||
dll_prefix: String,
|
||||
dll_suffix: String,
|
||||
crate_rejections: CrateRejections,
|
||||
@ -1034,7 +1034,7 @@ pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
|
||||
dcx.emit_err(errors::NoCrateWithTriple {
|
||||
span,
|
||||
crate_name,
|
||||
locator_triple: locator.triple.triple(),
|
||||
locator_triple: locator.triple.tuple(),
|
||||
add_info,
|
||||
found_crates,
|
||||
});
|
||||
|
@ -770,7 +770,7 @@ pub(crate) fn list_crate_metadata(
|
||||
root.stable_crate_id
|
||||
)?;
|
||||
writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
|
||||
writeln!(out, "triple {}", root.header.triple.triple())?;
|
||||
writeln!(out, "triple {}", root.header.triple.tuple())?;
|
||||
writeln!(out, "edition {}", root.edition)?;
|
||||
writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?;
|
||||
writeln!(
|
||||
|
@ -38,7 +38,7 @@
|
||||
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTuple};
|
||||
use table::TableBuilder;
|
||||
use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
|
||||
|
||||
@ -213,7 +213,7 @@ pub(crate) struct ProcMacroData {
|
||||
/// If you do modify this struct, also bump the [`METADATA_VERSION`] constant.
|
||||
#[derive(MetadataEncodable, MetadataDecodable)]
|
||||
pub(crate) struct CrateHeader {
|
||||
pub(crate) triple: TargetTriple,
|
||||
pub(crate) triple: TargetTuple,
|
||||
pub(crate) hash: Svh,
|
||||
pub(crate) name: Symbol,
|
||||
/// Whether this is the header for a proc-macro crate.
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fs::File;
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_errors::pluralize;
|
||||
@ -250,8 +252,8 @@ pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String
|
||||
}
|
||||
|
||||
let width = self.sess.diagnostic_width();
|
||||
let length_limit = width.saturating_sub(30);
|
||||
if regular.len() <= width {
|
||||
let length_limit = width / 2;
|
||||
if regular.len() <= width * 2 / 3 {
|
||||
return regular;
|
||||
}
|
||||
let short = self.ty_string_with_limit(ty, length_limit);
|
||||
@ -265,7 +267,20 @@ pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String
|
||||
*path = Some(path.take().unwrap_or_else(|| {
|
||||
self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
|
||||
}));
|
||||
match std::fs::write(path.as_ref().unwrap(), &format!("{regular}\n")) {
|
||||
let Ok(mut file) =
|
||||
File::options().create(true).read(true).append(true).open(&path.as_ref().unwrap())
|
||||
else {
|
||||
return regular;
|
||||
};
|
||||
|
||||
// Do not write the same type to the file multiple times.
|
||||
let mut contents = String::new();
|
||||
let _ = file.read_to_string(&mut contents);
|
||||
if let Some(_) = contents.lines().find(|line| line == ®ular) {
|
||||
return short;
|
||||
}
|
||||
|
||||
match write!(file, "{regular}\n") {
|
||||
Ok(_) => short,
|
||||
Err(_) => regular,
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol, sym,
|
||||
};
|
||||
use rustc_target::spec::{
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTriple,
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
@ -813,6 +813,7 @@ pub struct PrintRequest {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum PrintKind {
|
||||
FileNames,
|
||||
HostTuple,
|
||||
Sysroot,
|
||||
TargetLibdir,
|
||||
CrateName,
|
||||
@ -1116,7 +1117,7 @@ pub struct RemapPathScopeComponents: u8 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host_triple() -> &'static str {
|
||||
pub fn host_tuple() -> &'static str {
|
||||
// Get the host triple out of the build environment. This ensures that our
|
||||
// idea of the host triple is the same as for the set of libraries we've
|
||||
// actually built. We can't just take LLVM's host triple because they
|
||||
@ -1158,7 +1159,7 @@ fn default() -> Options {
|
||||
output_types: OutputTypes(BTreeMap::new()),
|
||||
search_paths: vec![],
|
||||
maybe_sysroot: None,
|
||||
target_triple: TargetTriple::from_triple(host_triple()),
|
||||
target_triple: TargetTuple::from_tuple(host_tuple()),
|
||||
test: false,
|
||||
incremental: None,
|
||||
untracked_state_hash: Default::default(),
|
||||
@ -1354,7 +1355,7 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: &
|
||||
// rust-lang/compiler-team#695. Warn unconditionally on usage to
|
||||
// raise awareness of the renaming. This code will be deleted in
|
||||
// October 2024.
|
||||
if opts.target_triple.triple() == "wasm32-wasi" {
|
||||
if opts.target_triple.tuple() == "wasm32-wasi" {
|
||||
early_dcx.early_warn(
|
||||
"the `wasm32-wasi` target is being renamed to \
|
||||
`wasm32-wasip1` and the `wasm32-wasi` target will be \
|
||||
@ -1945,6 +1946,7 @@ fn collect_print_requests(
|
||||
("crate-name", PrintKind::CrateName),
|
||||
("deployment-target", PrintKind::DeploymentTarget),
|
||||
("file-names", PrintKind::FileNames),
|
||||
("host-tuple", PrintKind::HostTuple),
|
||||
("link-args", PrintKind::LinkArgs),
|
||||
("native-static-libs", PrintKind::NativeStaticLibs),
|
||||
("relocation-models", PrintKind::RelocationModels),
|
||||
@ -2030,16 +2032,16 @@ fn collect_print_requests(
|
||||
prints
|
||||
}
|
||||
|
||||
pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTriple {
|
||||
pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
|
||||
match matches.opt_str("target") {
|
||||
Some(target) if target.ends_with(".json") => {
|
||||
let path = Path::new(&target);
|
||||
TargetTriple::from_path(path).unwrap_or_else(|_| {
|
||||
TargetTuple::from_path(path).unwrap_or_else(|_| {
|
||||
early_dcx.early_fatal(format!("target file {path:?} does not exist"))
|
||||
})
|
||||
}
|
||||
Some(target) => TargetTriple::TargetTriple(target),
|
||||
_ => TargetTriple::from_triple(host_triple()),
|
||||
Some(target) => TargetTuple::TargetTuple(target),
|
||||
_ => TargetTuple::from_tuple(host_tuple()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3009,7 +3011,7 @@ pub(crate) mod dep_tracking {
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_target::spec::{
|
||||
CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
|
||||
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTriple,
|
||||
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
|
||||
TlsModel, WasmCAbi,
|
||||
};
|
||||
|
||||
@ -3094,7 +3096,7 @@ fn hash(
|
||||
SanitizerSet,
|
||||
CFGuard,
|
||||
CFProtection,
|
||||
TargetTriple,
|
||||
TargetTuple,
|
||||
Edition,
|
||||
LinkerPluginLto,
|
||||
ResolveDocLinks,
|
||||
|
@ -29,7 +29,7 @@
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, TARGETS, Target, TargetTriple};
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, TARGETS, Target, TargetTuple};
|
||||
|
||||
use crate::Session;
|
||||
use crate::config::{CrateType, FmtDebug};
|
||||
@ -417,7 +417,7 @@ macro_rules! ins {
|
||||
|
||||
for target in TARGETS
|
||||
.iter()
|
||||
.map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
|
||||
.map(|target| Target::expect_builtin(&TargetTuple::from_tuple(target)))
|
||||
.chain(iter::once(current_target.clone()))
|
||||
{
|
||||
values_target_abi.insert(Symbol::intern(&target.options.abi));
|
||||
|
@ -9,7 +9,7 @@
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
|
||||
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple};
|
||||
|
||||
use crate::config::CrateType;
|
||||
use crate::parse::ParseSess;
|
||||
@ -179,13 +179,13 @@ pub(crate) struct EmbedSourceInsufficientDwarfVersion {
|
||||
#[diag(session_target_stack_protector_not_supported)]
|
||||
pub(crate) struct StackProtectorNotSupportedForTarget<'a> {
|
||||
pub(crate) stack_protector: StackProtector,
|
||||
pub(crate) target_triple: &'a TargetTriple,
|
||||
pub(crate) target_triple: &'a TargetTuple,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_target_small_data_threshold_not_supported)]
|
||||
pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> {
|
||||
pub(crate) target_triple: &'a TargetTriple,
|
||||
pub(crate) target_triple: &'a TargetTuple,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -383,7 +383,7 @@ struct BinaryFloatLiteralNotSupported {
|
||||
#[diag(session_unsupported_crate_type_for_target)]
|
||||
pub(crate) struct UnsupportedCrateTypeForTarget<'a> {
|
||||
pub(crate) crate_type: CrateType,
|
||||
pub(crate) target_triple: &'a TargetTriple,
|
||||
pub(crate) target_triple: &'a TargetTuple,
|
||||
}
|
||||
|
||||
pub fn report_lit_error(
|
||||
|
@ -152,7 +152,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
||||
}
|
||||
|
||||
pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
|
||||
let target = crate::config::host_triple();
|
||||
let target = crate::config::host_tuple();
|
||||
let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
|
||||
smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
|
||||
let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string()));
|
||||
@ -218,7 +218,7 @@ fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
|
||||
))?;
|
||||
|
||||
// if `dir` points target's dir, move up to the sysroot
|
||||
let mut sysroot_dir = if dir.ends_with(crate::config::host_triple()) {
|
||||
let mut sysroot_dir = if dir.ends_with(crate::config::host_tuple()) {
|
||||
dir.parent() // chop off `$target`
|
||||
.and_then(|p| p.parent()) // chop off `rustlib`
|
||||
.and_then(|p| p.parent()) // chop off `lib`
|
||||
|
@ -14,7 +14,7 @@
|
||||
use rustc_target::spec::{
|
||||
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
|
||||
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
|
||||
TargetTriple, TlsModel, WasmCAbi,
|
||||
TargetTuple, TlsModel, WasmCAbi,
|
||||
};
|
||||
|
||||
use crate::config::*;
|
||||
@ -146,7 +146,7 @@ pub struct Options {
|
||||
libs: Vec<NativeLib> [TRACKED],
|
||||
maybe_sysroot: Option<PathBuf> [UNTRACKED],
|
||||
|
||||
target_triple: TargetTriple [TRACKED],
|
||||
target_triple: TargetTuple [TRACKED],
|
||||
|
||||
/// Effective logical environment used by `env!`/`option_env!` macros
|
||||
logical_env: FxIndexMap<String, String> [TRACKED],
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_target::spec::TargetTriple;
|
||||
use rustc_target::spec::TargetTuple;
|
||||
|
||||
use crate::EarlyDiagCtxt;
|
||||
use crate::filesearch::make_target_lib_path;
|
||||
@ -52,7 +52,7 @@ pub fn matches(&self, kind: PathKind) -> bool {
|
||||
impl SearchPath {
|
||||
pub fn from_cli_opt(
|
||||
sysroot: &Path,
|
||||
triple: &TargetTriple,
|
||||
triple: &TargetTuple,
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
path: &str,
|
||||
is_unstable_enabled: bool,
|
||||
@ -80,7 +80,7 @@ pub fn from_cli_opt(
|
||||
);
|
||||
}
|
||||
|
||||
make_target_lib_path(sysroot, triple.triple()).join("builtin").join(stripped)
|
||||
make_target_lib_path(sysroot, triple.tuple()).join("builtin").join(stripped)
|
||||
}
|
||||
None => PathBuf::from(path),
|
||||
};
|
||||
|
@ -32,7 +32,7 @@
|
||||
use rustc_target::spec::{
|
||||
CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
|
||||
SmallDataThresholdSupport, SplitDebuginfo, StackProtector, SymbolVisibility, Target,
|
||||
TargetTriple, TlsModel,
|
||||
TargetTuple, TlsModel,
|
||||
};
|
||||
|
||||
use crate::code_stats::CodeStats;
|
||||
@ -451,12 +451,12 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
|
||||
/// directories are also returned, for example if `--sysroot` is used but tools are missing
|
||||
/// (#125246): we also add the bin directories to the sysroot where rustc is located.
|
||||
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
|
||||
let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple());
|
||||
let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_tuple());
|
||||
let fallback_sysroot_paths = filesearch::sysroot_candidates()
|
||||
.into_iter()
|
||||
// Ignore sysroot candidate if it was the same as the sysroot path we just used.
|
||||
.filter(|sysroot| *sysroot != self.sysroot)
|
||||
.map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple()));
|
||||
.map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_tuple()));
|
||||
let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);
|
||||
|
||||
if self_contained {
|
||||
@ -1023,7 +1023,7 @@ pub fn build_session(
|
||||
let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
|
||||
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
|
||||
|
||||
let host_triple = TargetTriple::from_triple(config::host_triple());
|
||||
let host_triple = TargetTuple::from_tuple(config::host_tuple());
|
||||
let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
|
||||
early_dcx.early_fatal(format!("Error loading host specification: {e}"))
|
||||
});
|
||||
@ -1074,8 +1074,8 @@ pub fn build_session(
|
||||
let mut psess = ParseSess::with_dcx(dcx, source_map);
|
||||
psess.assume_incomplete_release = sopts.unstable_opts.assume_incomplete_release;
|
||||
|
||||
let host_triple = config::host_triple();
|
||||
let target_triple = sopts.target_triple.triple();
|
||||
let host_triple = config::host_tuple();
|
||||
let target_triple = sopts.target_triple.tuple();
|
||||
let host_tlib_path = Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
|
||||
let target_tlib_path = if host_triple == target_triple {
|
||||
// Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
|
||||
|
@ -378,7 +378,6 @@
|
||||
aggregate_raw_ptr,
|
||||
alias,
|
||||
align,
|
||||
align_offset,
|
||||
alignment,
|
||||
all,
|
||||
alloc,
|
||||
|
@ -1,21 +1,21 @@
|
||||
//! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131)
|
||||
//!
|
||||
//! Rust targets a wide variety of usecases, and in the interest of flexibility,
|
||||
//! allows new target triples to be defined in configuration files. Most users
|
||||
//! allows new target tuples to be defined in configuration files. Most users
|
||||
//! will not need to care about these, but this is invaluable when porting Rust
|
||||
//! to a new platform, and allows for an unprecedented level of control over how
|
||||
//! the compiler works.
|
||||
//!
|
||||
//! # Using custom targets
|
||||
//!
|
||||
//! A target triple, as passed via `rustc --target=TRIPLE`, will first be
|
||||
//! A target tuple, as passed via `rustc --target=TUPLE`, will first be
|
||||
//! compared against the list of built-in targets. This is to ease distributing
|
||||
//! rustc (no need for configuration files) and also to hold these built-in
|
||||
//! targets as immutable and sacred. If `TRIPLE` is not one of the built-in
|
||||
//! targets, rustc will check if a file named `TRIPLE` exists. If it does, it
|
||||
//! targets as immutable and sacred. If `TUPLE` is not one of the built-in
|
||||
//! targets, rustc will check if a file named `TUPLE` exists. If it does, it
|
||||
//! will be loaded as the target configuration. If the file does not exist,
|
||||
//! rustc will search each directory in the environment variable
|
||||
//! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will
|
||||
//! `RUST_TARGET_PATH` for a file named `TUPLE.json`. The first one found will
|
||||
//! be loaded. If no file is found in any of those directories, a fatal error
|
||||
//! will be given.
|
||||
//!
|
||||
@ -1586,17 +1586,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
|
||||
macro_rules! supported_targets {
|
||||
( $(($triple:literal, $module:ident),)+ ) => {
|
||||
( $(($tuple:literal, $module:ident),)+ ) => {
|
||||
mod targets {
|
||||
$(pub(crate) mod $module;)+
|
||||
}
|
||||
|
||||
/// List of supported targets
|
||||
pub const TARGETS: &[&str] = &[$($triple),+];
|
||||
pub const TARGETS: &[&str] = &[$($tuple),+];
|
||||
|
||||
fn load_builtin(target: &str) -> Option<Target> {
|
||||
let mut t = match target {
|
||||
$( $triple => targets::$module::target(), )+
|
||||
$( $tuple => targets::$module::target(), )+
|
||||
_ => return None,
|
||||
};
|
||||
t.is_builtin = true;
|
||||
@ -2005,9 +2005,9 @@ pub fn warning_messages(&self) -> Vec<String> {
|
||||
/// Every field here must be specified, and has no default value.
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct Target {
|
||||
/// Unversioned target triple to pass to LLVM.
|
||||
/// Unversioned target tuple to pass to LLVM.
|
||||
///
|
||||
/// Target triples can optionally contain an OS version (notably Apple targets), which rustc
|
||||
/// Target tuples can optionally contain an OS version (notably Apple targets), which rustc
|
||||
/// cannot know without querying the environment.
|
||||
///
|
||||
/// Use `rustc_codegen_ssa::back::versioned_llvm_target` if you need the full LLVM target.
|
||||
@ -3477,28 +3477,28 @@ macro_rules! key {
|
||||
}
|
||||
|
||||
/// Load a built-in target
|
||||
pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
|
||||
match *target_triple {
|
||||
TargetTriple::TargetTriple(ref target_triple) => {
|
||||
load_builtin(target_triple).expect("built-in target")
|
||||
pub fn expect_builtin(target_tuple: &TargetTuple) -> Target {
|
||||
match *target_tuple {
|
||||
TargetTuple::TargetTuple(ref target_tuple) => {
|
||||
load_builtin(target_tuple).expect("built-in target")
|
||||
}
|
||||
TargetTriple::TargetJson { .. } => {
|
||||
TargetTuple::TargetJson { .. } => {
|
||||
panic!("built-in targets doesn't support target-paths")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for a JSON file specifying the given target triple.
|
||||
/// Search for a JSON file specifying the given target tuple.
|
||||
///
|
||||
/// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
|
||||
/// sysroot under the target-triple's `rustlib` directory. Note that it could also just be a
|
||||
/// sysroot under the target-tuple's `rustlib` directory. Note that it could also just be a
|
||||
/// bare filename already, so also check for that. If one of the hardcoded targets we know
|
||||
/// about, just return it directly.
|
||||
///
|
||||
/// The error string could come from any of the APIs called, including filesystem access and
|
||||
/// JSON decoding.
|
||||
pub fn search(
|
||||
target_triple: &TargetTriple,
|
||||
target_tuple: &TargetTuple,
|
||||
sysroot: &Path,
|
||||
) -> Result<(Target, TargetWarnings), String> {
|
||||
use std::{env, fs};
|
||||
@ -3509,16 +3509,16 @@ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
|
||||
Target::from_json(obj)
|
||||
}
|
||||
|
||||
match *target_triple {
|
||||
TargetTriple::TargetTriple(ref target_triple) => {
|
||||
// check if triple is in list of built-in targets
|
||||
if let Some(t) = load_builtin(target_triple) {
|
||||
match *target_tuple {
|
||||
TargetTuple::TargetTuple(ref target_tuple) => {
|
||||
// check if tuple is in list of built-in targets
|
||||
if let Some(t) = load_builtin(target_tuple) {
|
||||
return Ok((t, TargetWarnings::empty()));
|
||||
}
|
||||
|
||||
// search for a file named `target_triple`.json in RUST_TARGET_PATH
|
||||
// search for a file named `target_tuple`.json in RUST_TARGET_PATH
|
||||
let path = {
|
||||
let mut target = target_triple.to_string();
|
||||
let mut target = target_tuple.to_string();
|
||||
target.push_str(".json");
|
||||
PathBuf::from(target)
|
||||
};
|
||||
@ -3532,9 +3532,9 @@ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
|
||||
}
|
||||
}
|
||||
|
||||
// Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
|
||||
// Additionally look in the sysroot under `lib/rustlib/<tuple>/target.json`
|
||||
// as a fallback.
|
||||
let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_triple);
|
||||
let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_tuple);
|
||||
let p = PathBuf::from_iter([
|
||||
Path::new(sysroot),
|
||||
Path::new(&rustlib_path),
|
||||
@ -3544,9 +3544,9 @@ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
|
||||
return load_file(&p);
|
||||
}
|
||||
|
||||
Err(format!("Could not find specification for target {target_triple:?}"))
|
||||
Err(format!("Could not find specification for target {target_tuple:?}"))
|
||||
}
|
||||
TargetTriple::TargetJson { ref contents, .. } => {
|
||||
TargetTuple::TargetJson { ref contents, .. } => {
|
||||
let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
|
||||
Target::from_json(obj)
|
||||
}
|
||||
@ -3751,44 +3751,44 @@ macro_rules! target_option_val {
|
||||
}
|
||||
}
|
||||
|
||||
/// Either a target triple string or a path to a JSON file.
|
||||
/// Either a target tuple string or a path to a JSON file.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TargetTriple {
|
||||
TargetTriple(String),
|
||||
pub enum TargetTuple {
|
||||
TargetTuple(String),
|
||||
TargetJson {
|
||||
/// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to
|
||||
/// inconsistencies as it is discarded during serialization.
|
||||
path_for_rustdoc: PathBuf,
|
||||
triple: String,
|
||||
tuple: String,
|
||||
contents: String,
|
||||
},
|
||||
}
|
||||
|
||||
// Use a manual implementation to ignore the path field
|
||||
impl PartialEq for TargetTriple {
|
||||
impl PartialEq for TargetTuple {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::TargetTriple(l0), Self::TargetTriple(r0)) => l0 == r0,
|
||||
(Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0,
|
||||
(
|
||||
Self::TargetJson { path_for_rustdoc: _, triple: l_triple, contents: l_contents },
|
||||
Self::TargetJson { path_for_rustdoc: _, triple: r_triple, contents: r_contents },
|
||||
) => l_triple == r_triple && l_contents == r_contents,
|
||||
Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents },
|
||||
Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents },
|
||||
) => l_tuple == r_tuple && l_contents == r_contents,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use a manual implementation to ignore the path field
|
||||
impl Hash for TargetTriple {
|
||||
impl Hash for TargetTuple {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) -> () {
|
||||
match self {
|
||||
TargetTriple::TargetTriple(triple) => {
|
||||
TargetTuple::TargetTuple(tuple) => {
|
||||
0u8.hash(state);
|
||||
triple.hash(state)
|
||||
tuple.hash(state)
|
||||
}
|
||||
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
|
||||
TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
|
||||
1u8.hash(state);
|
||||
triple.hash(state);
|
||||
tuple.hash(state);
|
||||
contents.hash(state)
|
||||
}
|
||||
}
|
||||
@ -3796,45 +3796,45 @@ fn hash<H: Hasher>(&self, state: &mut H) -> () {
|
||||
}
|
||||
|
||||
// Use a manual implementation to prevent encoding the target json file path in the crate metadata
|
||||
impl<S: Encoder> Encodable<S> for TargetTriple {
|
||||
impl<S: Encoder> Encodable<S> for TargetTuple {
|
||||
fn encode(&self, s: &mut S) {
|
||||
match self {
|
||||
TargetTriple::TargetTriple(triple) => {
|
||||
TargetTuple::TargetTuple(tuple) => {
|
||||
s.emit_u8(0);
|
||||
s.emit_str(triple);
|
||||
s.emit_str(tuple);
|
||||
}
|
||||
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
|
||||
TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => {
|
||||
s.emit_u8(1);
|
||||
s.emit_str(triple);
|
||||
s.emit_str(tuple);
|
||||
s.emit_str(contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for TargetTriple {
|
||||
impl<D: Decoder> Decodable<D> for TargetTuple {
|
||||
fn decode(d: &mut D) -> Self {
|
||||
match d.read_u8() {
|
||||
0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
|
||||
1 => TargetTriple::TargetJson {
|
||||
0 => TargetTuple::TargetTuple(d.read_str().to_owned()),
|
||||
1 => TargetTuple::TargetJson {
|
||||
path_for_rustdoc: PathBuf::new(),
|
||||
triple: d.read_str().to_owned(),
|
||||
tuple: d.read_str().to_owned(),
|
||||
contents: d.read_str().to_owned(),
|
||||
},
|
||||
_ => {
|
||||
panic!("invalid enum variant tag while decoding `TargetTriple`, expected 0..2");
|
||||
panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetTriple {
|
||||
/// Creates a target triple from the passed target triple string.
|
||||
pub fn from_triple(triple: &str) -> Self {
|
||||
TargetTriple::TargetTriple(triple.into())
|
||||
impl TargetTuple {
|
||||
/// Creates a target tuple from the passed target tuple string.
|
||||
pub fn from_tuple(tuple: &str) -> Self {
|
||||
TargetTuple::TargetTuple(tuple.into())
|
||||
}
|
||||
|
||||
/// Creates a target triple from the passed target path.
|
||||
/// Creates a target tuple from the passed target path.
|
||||
pub fn from_path(path: &Path) -> Result<Self, io::Error> {
|
||||
let canonicalized_path = try_canonicalize(path)?;
|
||||
let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
|
||||
@ -3843,46 +3843,47 @@ pub fn from_path(path: &Path) -> Result<Self, io::Error> {
|
||||
format!("target path {canonicalized_path:?} is not a valid file: {err}"),
|
||||
)
|
||||
})?;
|
||||
let triple = canonicalized_path
|
||||
let tuple = canonicalized_path
|
||||
.file_stem()
|
||||
.expect("target path must not be empty")
|
||||
.to_str()
|
||||
.expect("target path must be valid unicode")
|
||||
.to_owned();
|
||||
Ok(TargetTriple::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents })
|
||||
Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents })
|
||||
}
|
||||
|
||||
/// Returns a string triple for this target.
|
||||
/// Returns a string tuple for this target.
|
||||
///
|
||||
/// If this target is a path, the file name (without extension) is returned.
|
||||
pub fn triple(&self) -> &str {
|
||||
pub fn tuple(&self) -> &str {
|
||||
match *self {
|
||||
TargetTriple::TargetTriple(ref triple)
|
||||
| TargetTriple::TargetJson { ref triple, .. } => triple,
|
||||
TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => {
|
||||
tuple
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an extended string triple for this target.
|
||||
/// Returns an extended string tuple for this target.
|
||||
///
|
||||
/// If this target is a path, a hash of the path is appended to the triple returned
|
||||
/// by `triple()`.
|
||||
pub fn debug_triple(&self) -> String {
|
||||
/// If this target is a path, a hash of the path is appended to the tuple returned
|
||||
/// by `tuple()`.
|
||||
pub fn debug_tuple(&self) -> String {
|
||||
use std::hash::DefaultHasher;
|
||||
|
||||
match self {
|
||||
TargetTriple::TargetTriple(triple) => triple.to_owned(),
|
||||
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents: content } => {
|
||||
TargetTuple::TargetTuple(tuple) => tuple.to_owned(),
|
||||
TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
content.hash(&mut hasher);
|
||||
let hash = hasher.finish();
|
||||
format!("{triple}-{hash}")
|
||||
format!("{tuple}-{hash}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TargetTriple {
|
||||
impl fmt::Display for TargetTuple {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.debug_triple())
|
||||
write!(f, "{}", self.debug_tuple())
|
||||
}
|
||||
}
|
||||
|
@ -766,6 +766,67 @@ fn cmp_fn_sig(
|
||||
values
|
||||
}
|
||||
|
||||
pub fn cmp_traits(
|
||||
&self,
|
||||
def_id1: DefId,
|
||||
args1: &[ty::GenericArg<'tcx>],
|
||||
def_id2: DefId,
|
||||
args2: &[ty::GenericArg<'tcx>],
|
||||
) -> (DiagStyledString, DiagStyledString) {
|
||||
let mut values = (DiagStyledString::new(), DiagStyledString::new());
|
||||
|
||||
if def_id1 != def_id2 {
|
||||
values.0.push_highlighted(self.tcx.def_path_str(def_id1).as_str());
|
||||
values.1.push_highlighted(self.tcx.def_path_str(def_id2).as_str());
|
||||
} else {
|
||||
values.0.push_normal(self.tcx.item_name(def_id1).as_str());
|
||||
values.1.push_normal(self.tcx.item_name(def_id2).as_str());
|
||||
}
|
||||
|
||||
if args1.len() != args2.len() {
|
||||
let (pre, post) = if args1.len() > 0 { ("<", ">") } else { ("", "") };
|
||||
values.0.push_normal(format!(
|
||||
"{pre}{}{post}",
|
||||
args1.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
|
||||
));
|
||||
let (pre, post) = if args2.len() > 0 { ("<", ">") } else { ("", "") };
|
||||
values.1.push_normal(format!(
|
||||
"{pre}{}{post}",
|
||||
args2.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
|
||||
));
|
||||
return values;
|
||||
}
|
||||
|
||||
if args1.len() > 0 {
|
||||
values.0.push_normal("<");
|
||||
values.1.push_normal("<");
|
||||
}
|
||||
for (i, (a, b)) in std::iter::zip(args1, args2).enumerate() {
|
||||
let a_str = a.to_string();
|
||||
let b_str = b.to_string();
|
||||
if let (Some(a), Some(b)) = (a.as_type(), b.as_type()) {
|
||||
let (a, b) = self.cmp(a, b);
|
||||
values.0.0.extend(a.0);
|
||||
values.1.0.extend(b.0);
|
||||
} else if a_str != b_str {
|
||||
values.0.push_highlighted(a_str);
|
||||
values.1.push_highlighted(b_str);
|
||||
} else {
|
||||
values.0.push_normal(a_str);
|
||||
values.1.push_normal(b_str);
|
||||
}
|
||||
if i + 1 < args1.len() {
|
||||
values.0.push_normal(", ");
|
||||
values.1.push_normal(", ");
|
||||
}
|
||||
}
|
||||
if args1.len() > 0 {
|
||||
values.0.push_normal(">");
|
||||
values.1.push_normal(">");
|
||||
}
|
||||
values
|
||||
}
|
||||
|
||||
/// Compares two given types, eliding parts that are the same between them and highlighting
|
||||
/// relevant differences, and return two representation of those types for highlighted printing.
|
||||
pub fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagStyledString, DiagStyledString) {
|
||||
|
@ -6,8 +6,8 @@
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, StringPart, Suggestions, pluralize,
|
||||
struct_span_code_err,
|
||||
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions,
|
||||
pluralize, struct_span_code_err,
|
||||
};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
@ -328,6 +328,11 @@ pub fn report_selection_error(
|
||||
}
|
||||
} else if let Some(custom_explanation) = safe_transmute_explanation {
|
||||
err.span_label(span, custom_explanation);
|
||||
} else if explanation.len() > self.tcx.sess.diagnostic_width() {
|
||||
// Really long types don't look good as span labels, instead move it
|
||||
// to a `help`.
|
||||
err.span_label(span, "unsatisfied trait bound");
|
||||
err.help(explanation);
|
||||
} else {
|
||||
err.span_label(span, explanation);
|
||||
}
|
||||
@ -1832,21 +1837,81 @@ pub(super) fn report_similar_impl_candidates(
|
||||
if impl_trait_ref.references_error() {
|
||||
return false;
|
||||
}
|
||||
let self_ty = impl_trait_ref.self_ty().to_string();
|
||||
err.highlighted_help(vec![
|
||||
StringPart::normal(format!(
|
||||
"the trait `{}` ",
|
||||
impl_trait_ref.print_trait_sugared()
|
||||
)),
|
||||
StringPart::highlighted("is"),
|
||||
|
||||
if let [child, ..] = &err.children[..]
|
||||
&& child.level == Level::Help
|
||||
&& let Some(line) = child.messages.get(0)
|
||||
&& let Some(line) = line.0.as_str()
|
||||
&& line.starts_with("the trait")
|
||||
&& line.contains("is not implemented for")
|
||||
{
|
||||
// HACK(estebank): we remove the pre-existing
|
||||
// "the trait `X` is not implemented for" note, which only happens if there
|
||||
// was a custom label. We do this because we want that note to always be the
|
||||
// first, and making this logic run earlier will get tricky. For now, we
|
||||
// instead keep the logic the same and modify the already constructed error
|
||||
// to avoid the wording duplication.
|
||||
err.children.remove(0);
|
||||
}
|
||||
|
||||
let traits = self.cmp_traits(
|
||||
obligation_trait_ref.def_id,
|
||||
&obligation_trait_ref.args[1..],
|
||||
impl_trait_ref.def_id,
|
||||
&impl_trait_ref.args[1..],
|
||||
);
|
||||
let traits_content = (traits.0.content(), traits.1.content());
|
||||
let types = self.cmp(obligation_trait_ref.self_ty(), impl_trait_ref.self_ty());
|
||||
let types_content = (types.0.content(), types.1.content());
|
||||
let mut msg = vec![StringPart::normal("the trait `")];
|
||||
if traits_content.0 == traits_content.1 {
|
||||
msg.push(StringPart::normal(
|
||||
impl_trait_ref.print_trait_sugared().to_string(),
|
||||
));
|
||||
} else {
|
||||
msg.extend(traits.0.0);
|
||||
}
|
||||
msg.extend([
|
||||
StringPart::normal("` "),
|
||||
StringPart::highlighted("is not"),
|
||||
StringPart::normal(" implemented for `"),
|
||||
if let [TypeError::Sorts(_)] = &terrs[..] {
|
||||
StringPart::normal(self_ty)
|
||||
} else {
|
||||
StringPart::highlighted(self_ty)
|
||||
},
|
||||
StringPart::normal("`"),
|
||||
]);
|
||||
if types_content.0 == types_content.1 {
|
||||
let ty =
|
||||
self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None);
|
||||
msg.push(StringPart::normal(ty));
|
||||
} else {
|
||||
msg.extend(types.0.0);
|
||||
}
|
||||
msg.push(StringPart::normal("`"));
|
||||
if types_content.0 == types_content.1 {
|
||||
msg.push(StringPart::normal("\nbut trait `"));
|
||||
msg.extend(traits.1.0);
|
||||
msg.extend([
|
||||
StringPart::normal("` "),
|
||||
StringPart::highlighted("is"),
|
||||
StringPart::normal(" implemented for it"),
|
||||
]);
|
||||
} else if traits_content.0 == traits_content.1 {
|
||||
msg.extend([
|
||||
StringPart::normal("\nbut it "),
|
||||
StringPart::highlighted("is"),
|
||||
StringPart::normal(" implemented for `"),
|
||||
]);
|
||||
msg.extend(types.1.0);
|
||||
msg.push(StringPart::normal("`"));
|
||||
} else {
|
||||
msg.push(StringPart::normal("\nbut trait `"));
|
||||
msg.extend(traits.1.0);
|
||||
msg.extend([
|
||||
StringPart::normal("` "),
|
||||
StringPart::highlighted("is"),
|
||||
StringPart::normal(" implemented for `"),
|
||||
]);
|
||||
msg.extend(types.1.0);
|
||||
msg.push(StringPart::normal("`"));
|
||||
}
|
||||
err.highlighted_help(msg);
|
||||
|
||||
if let [TypeError::Sorts(exp_found)] = &terrs[..] {
|
||||
let exp_found = self.resolve_vars_if_possible(*exp_found);
|
||||
@ -2475,12 +2540,16 @@ fn try_to_add_help_message(
|
||||
&& self.tcx.trait_impls_of(trait_def_id).is_empty()
|
||||
&& !self.tcx.trait_is_auto(trait_def_id)
|
||||
&& !self.tcx.trait_is_alias(trait_def_id)
|
||||
&& trait_predicate.polarity() == ty::PredicatePolarity::Positive
|
||||
{
|
||||
err.span_help(
|
||||
self.tcx.def_span(trait_def_id),
|
||||
crate::fluent_generated::trait_selection_trait_has_no_impls,
|
||||
);
|
||||
} else if !suggested && !unsatisfied_const {
|
||||
} else if !suggested
|
||||
&& !unsatisfied_const
|
||||
&& trait_predicate.polarity() == ty::PredicatePolarity::Positive
|
||||
{
|
||||
// Can't show anything else useful, try to find similar impls.
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
|
||||
if !self.report_similar_impl_candidates(
|
||||
|
@ -3563,17 +3563,34 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
)]);
|
||||
}
|
||||
ObligationCauseCode::OpaqueReturnType(expr_info) => {
|
||||
if let Some((expr_ty, hir_id)) = expr_info {
|
||||
let expr_ty = self.tcx.short_ty_string(expr_ty, long_ty_file);
|
||||
let expr = self.infcx.tcx.hir().expect_expr(hir_id);
|
||||
err.span_label(
|
||||
expr.span,
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"return type was inferred to be `{expr_ty}` here",
|
||||
)),
|
||||
);
|
||||
suggest_remove_deref(err, &expr);
|
||||
}
|
||||
let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
|
||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
||||
let expr = tcx.hir().expect_expr(hir_id);
|
||||
(expr_ty, expr)
|
||||
} else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
|
||||
&& let body = tcx.hir().body(body_id)
|
||||
&& let hir::ExprKind::Block(block, _) = body.value.kind
|
||||
&& let Some(expr) = block.expr
|
||||
&& let Some(expr_ty) = self
|
||||
.typeck_results
|
||||
.as_ref()
|
||||
.and_then(|typeck| typeck.node_type_opt(expr.hir_id))
|
||||
&& let Some(pred) = predicate.as_clause()
|
||||
&& let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
||||
&& self.can_eq(param_env, pred.self_ty(), expr_ty)
|
||||
{
|
||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
||||
(expr_ty, expr)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
err.span_label(
|
||||
expr.span,
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"return type was inferred to be `{expr_ty}` here",
|
||||
)),
|
||||
);
|
||||
suggest_remove_deref(err, &expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3680,6 +3697,9 @@ pub fn suggest_derive(
|
||||
err: &mut Diag<'_>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
if trait_pred.polarity() == ty::PredicatePolarity::Negative {
|
||||
return;
|
||||
}
|
||||
let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
|
||||
return;
|
||||
};
|
||||
|
@ -136,7 +136,6 @@ impl<T, const N: usize> IntoIter<T, N> {
|
||||
/// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
|
||||
/// ```
|
||||
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
|
||||
#[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
|
||||
pub const unsafe fn new_unchecked(
|
||||
buffer: [MaybeUninit<T>; N],
|
||||
initialized: Range<usize>,
|
||||
@ -199,7 +198,6 @@ impl<T, const N: usize> IntoIter<T, N> {
|
||||
/// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
|
||||
/// ```
|
||||
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
|
||||
#[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
|
||||
pub const fn empty() -> Self {
|
||||
let buffer = [const { MaybeUninit::uninit() }; N];
|
||||
let initialized = 0..0;
|
||||
|
@ -1515,7 +1515,6 @@ pub const fn is_ascii_digit(&self) -> bool {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[unstable(feature = "is_ascii_octdigit", issue = "101288")]
|
||||
#[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_octdigit(&self) -> bool {
|
||||
matches!(*self, '0'..='7')
|
||||
|
@ -112,11 +112,8 @@
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(const_align_of_val)]
|
||||
#![feature(const_align_of_val_raw)]
|
||||
#![feature(const_align_offset)]
|
||||
#![feature(const_alloc_layout)]
|
||||
#![feature(const_arguments_as_str)]
|
||||
#![feature(const_array_into_iter_constructors)]
|
||||
#![feature(const_bigint_helper_methods)]
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_char_encode_utf16)]
|
||||
#![feature(const_eval_select)]
|
||||
@ -125,17 +122,14 @@
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_nonnull_new)]
|
||||
#![feature(const_num_midpoint)]
|
||||
#![feature(const_option_ext)]
|
||||
#![feature(const_pin_2)]
|
||||
#![feature(const_pointer_is_aligned)]
|
||||
#![feature(const_ptr_is_null)]
|
||||
#![feature(const_ptr_sub_ptr)]
|
||||
#![feature(const_raw_ptr_comparison)]
|
||||
#![feature(const_size_of_val)]
|
||||
#![feature(const_size_of_val_raw)]
|
||||
#![feature(const_sockaddr_setters)]
|
||||
#![feature(const_strict_overflow_ops)]
|
||||
#![feature(const_swap)]
|
||||
#![feature(const_try)]
|
||||
#![feature(const_type_id)]
|
||||
@ -167,7 +161,6 @@
|
||||
#![feature(unchecked_neg)]
|
||||
#![feature(unchecked_shifts)]
|
||||
#![feature(utf16_extra)]
|
||||
#![feature(utf16_extra_const)]
|
||||
#![feature(variant_count)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
|
@ -338,7 +338,6 @@ pub const fn uninit() -> MaybeUninit<T> {
|
||||
/// let data = read(&mut buf);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_uninit_array", issue = "96097")]
|
||||
#[rustc_const_unstable(feature = "const_maybe_uninit_uninit_array", issue = "96097")]
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
pub const fn uninit_array<const N: usize>() -> [Self; N] {
|
||||
@ -946,7 +945,6 @@ pub unsafe fn assume_init_drop(&mut self) {
|
||||
/// assert_eq!(array, [0, 1, 2]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")]
|
||||
#[rustc_const_unstable(feature = "const_maybe_uninit_array_assume_init", issue = "96097")]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
|
||||
@ -973,7 +971,6 @@ pub unsafe fn assume_init_drop(&mut self) {
|
||||
///
|
||||
/// [`assume_init_ref`]: MaybeUninit::assume_init_ref
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
|
||||
// SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
|
||||
@ -995,7 +992,6 @@ pub unsafe fn assume_init_drop(&mut self) {
|
||||
///
|
||||
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||
@ -1005,7 +1001,6 @@ pub unsafe fn assume_init_drop(&mut self) {
|
||||
|
||||
/// Gets a pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
this.as_ptr() as *const T
|
||||
@ -1013,7 +1008,6 @@ pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
|
||||
/// Gets a mutable pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
|
||||
this.as_mut_ptr() as *mut T
|
||||
|
@ -373,7 +373,6 @@ pub const fn is_documentation(&self) -> bool {
|
||||
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
|
||||
/// ```
|
||||
#[unstable(feature = "ip", issue = "27709")]
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
|
@ -748,7 +748,6 @@ pub const fn is_sign_negative(self) -> bool {
|
||||
/// [`MAX`]: Self::MAX
|
||||
#[inline]
|
||||
#[unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
pub const fn next_up(self) -> Self {
|
||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||
// denormals to zero. This is in general unsound and unsupported, but here
|
||||
@ -797,7 +796,6 @@ pub const fn next_up(self) -> Self {
|
||||
/// [`MAX`]: Self::MAX
|
||||
#[inline]
|
||||
#[unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
pub const fn next_down(self) -> Self {
|
||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||
// denormals to zero. This is in general unsound and unsupported, but here
|
||||
|
@ -765,7 +765,6 @@ pub fn is_negative(self) -> bool {
|
||||
/// [`MAX`]: Self::MAX
|
||||
#[inline]
|
||||
#[unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
pub const fn next_up(self) -> Self {
|
||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||
// denormals to zero. This is in general unsound and unsupported, but here
|
||||
@ -814,7 +813,6 @@ pub const fn next_up(self) -> Self {
|
||||
/// [`MAX`]: Self::MAX
|
||||
#[inline]
|
||||
#[unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
|
||||
pub const fn next_down(self) -> Self {
|
||||
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
|
||||
// denormals to zero. This is in general unsound and unsupported, but here
|
||||
|
@ -477,7 +477,6 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -573,7 +572,6 @@ pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -629,7 +627,6 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -725,7 +722,6 @@ pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -781,7 +777,6 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -895,7 +890,6 @@ pub const fn checked_div(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -969,7 +963,6 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1042,7 +1035,6 @@ pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1115,7 +1107,6 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1203,7 +1194,6 @@ pub const fn checked_neg(self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")]
|
||||
///
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1266,7 +1256,6 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1325,7 +1314,6 @@ pub const fn strict_shl(self, rhs: u32) -> Self {
|
||||
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "unbounded_shifts", issue = "129375")]
|
||||
#[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1391,7 +1379,6 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1452,7 +1439,6 @@ pub const fn strict_shr(self, rhs: u32) -> Self {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "unbounded_shifts", issue = "129375")]
|
||||
#[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1519,7 +1505,6 @@ pub const fn checked_abs(self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1594,7 +1579,6 @@ pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -2368,7 +2352,6 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
|
||||
/// assert_eq!((sum1, sum0), (6, 8));
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -2476,7 +2459,6 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
||||
#[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")]
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
|
@ -114,7 +114,6 @@ macro_rules! midpoint_impl {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "num_midpoint", issue = "110840")]
|
||||
#[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -142,7 +141,6 @@ pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
|
||||
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "num_midpoint", issue = "110840")]
|
||||
#[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -170,7 +168,6 @@ pub const fn midpoint(self, rhs: Self) -> Self {
|
||||
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "num_midpoint", issue = "110840")]
|
||||
#[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -196,7 +193,6 @@ pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
|
||||
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "num_midpoint", issue = "110840")]
|
||||
#[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -229,7 +225,6 @@ macro_rules! widening_impl {
|
||||
/// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -320,7 +315,6 @@ pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -915,7 +909,6 @@ pub const fn is_ascii_digit(&self) -> bool {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[unstable(feature = "is_ascii_octdigit", issue = "101288")]
|
||||
#[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_octdigit(&self) -> bool {
|
||||
matches!(*self, b'0'..=b'7')
|
||||
@ -1195,7 +1188,6 @@ impl u16 {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[unstable(feature = "utf16_extra", issue = "94919")]
|
||||
#[rustc_const_unstable(feature = "utf16_extra_const", issue = "94919")]
|
||||
#[inline]
|
||||
pub const fn is_utf16_surrogate(self) -> bool {
|
||||
matches!(self, 0xD800..=0xDFFF)
|
||||
|
@ -1474,7 +1474,6 @@ pub const fn ilog10(self) -> u32 {
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "num_midpoint", issue = "110840")]
|
||||
#[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
|
@ -524,7 +524,6 @@ pub const fn checked_add(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -626,7 +625,6 @@ pub const fn checked_add_signed(self, rhs: $SignedT) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -691,7 +689,6 @@ pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -873,7 +870,6 @@ pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -975,7 +971,6 @@ pub const fn checked_div(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
@ -1035,7 +1030,6 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
@ -1097,7 +1091,6 @@ pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
@ -1159,7 +1152,6 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
@ -1392,7 +1384,6 @@ pub const fn checked_neg(self) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")]
|
||||
///
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1455,7 +1446,6 @@ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1514,7 +1504,6 @@ pub const fn strict_shl(self, rhs: u32) -> Self {
|
||||
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "unbounded_shifts", issue = "129375")]
|
||||
#[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1580,7 +1569,6 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1639,7 +1627,6 @@ pub const fn strict_shr(self, rhs: u32) -> Self {
|
||||
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "unbounded_shifts", issue = "129375")]
|
||||
#[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1714,7 +1701,6 @@ pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||
#[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")]
|
||||
/// ```
|
||||
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
|
||||
#[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -2290,7 +2276,6 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
|
||||
/// assert_eq!((sum1, sum0), (9, 6));
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -2382,7 +2367,6 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
||||
#[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")]
|
||||
/// ```
|
||||
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
|
||||
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
|
@ -240,7 +240,6 @@ pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self {
|
||||
///
|
||||
/// The pointer can be later reconstructed with [`from_raw_parts`].
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[inline]
|
||||
pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata) {
|
||||
(self.cast(), metadata(self))
|
||||
@ -316,7 +315,6 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
|
||||
/// ```
|
||||
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
|
||||
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
|
||||
@ -1360,15 +1358,6 @@ pub unsafe fn read_volatile(self) -> T
|
||||
/// beyond the allocation that the pointer points into. It is up to the caller to ensure that
|
||||
/// the returned offset is correct in all terms other than alignment.
|
||||
///
|
||||
/// When this is called during compile-time evaluation (which is unstable), the implementation
|
||||
/// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
|
||||
/// actual alignment of pointers is not known yet during compile-time, so an offset with
|
||||
/// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
|
||||
/// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
|
||||
/// known, so the execution has to be correct for either choice. It is therefore impossible to
|
||||
/// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
|
||||
/// for unstable APIs.)
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The function panics if `align` is not a power-of-two.
|
||||
@ -1397,8 +1386,7 @@ pub unsafe fn read_volatile(self) -> T
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "align_offset", since = "1.36.0")]
|
||||
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
|
||||
pub const fn align_offset(self, align: usize) -> usize
|
||||
pub fn align_offset(self, align: usize) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1433,94 +1421,10 @@ pub const fn align_offset(self, align: usize) -> usize
|
||||
/// assert!(ptr.is_aligned());
|
||||
/// assert!(!ptr.wrapping_byte_add(1).is_aligned());
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// is never aligned if cast to a type with a stricter alignment than the reference's
|
||||
/// underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let data = AlignedI32(42);
|
||||
/// let ptr = &data as *const AlignedI32;
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
|
||||
/// assert!(!ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
|
||||
/// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.cast::<AlignedI64>().is_aligned(),
|
||||
/// runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = 40 as *const AlignedI32;
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // For pointers with a known address, runtime and compiletime behavior are identical.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
|
||||
/// assert!(ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "pointer_is_aligned", since = "1.79.0")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned(self) -> bool
|
||||
pub fn is_aligned(self) -> bool
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1557,105 +1461,15 @@ pub const fn is_aligned(self) -> bool
|
||||
///
|
||||
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// cannot be stricter aligned than the reference's underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let data = AlignedI32(42);
|
||||
/// let ptr = &data as *const AlignedI32;
|
||||
///
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
///
|
||||
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
|
||||
/// assert!(!ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
|
||||
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.is_aligned_to(8),
|
||||
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = 40 as *const u8;
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
/// assert!(ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.is_aligned_to(16));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned_to(self, align: usize) -> bool {
|
||||
pub fn is_aligned_to(self, align: usize) -> bool {
|
||||
if !align.is_power_of_two() {
|
||||
panic!("is_aligned_to: align is not a power-of-two");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn runtime_impl(ptr: *const (), align: usize) -> bool {
|
||||
ptr.addr() & (align - 1) == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
const fn const_impl(ptr: *const (), align: usize) -> bool {
|
||||
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
||||
ptr.align_offset(align) == 0
|
||||
}
|
||||
|
||||
// The cast to `()` is used to
|
||||
// 1. deal with fat pointers; and
|
||||
// 2. ensure that `align_offset` (in `const_impl`) doesn't actually try to compute an offset.
|
||||
const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
|
||||
self.addr() & (align - 1) == 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -1714,7 +1528,6 @@ pub const fn is_empty(self) -> bool {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
pub const fn as_ptr(self) -> *const T {
|
||||
self as *const T
|
||||
}
|
||||
@ -1814,7 +1627,6 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_ptr(self) -> *const T {
|
||||
self as *const T
|
||||
}
|
||||
@ -1832,7 +1644,6 @@ pub const fn as_ptr(self) -> *const T {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_slice(self) -> *const [T] {
|
||||
self
|
||||
}
|
||||
|
@ -1852,9 +1852,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||
///
|
||||
/// Any questions go to @nagisa.
|
||||
#[allow(ptr_to_integer_transmute_in_consts)]
|
||||
#[lang = "align_offset"]
|
||||
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
|
||||
pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
|
||||
pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
|
||||
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
|
||||
// 1, where the method versions of these operations are not inlined.
|
||||
use intrinsics::{
|
||||
@ -1915,11 +1913,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||
|
||||
let stride = mem::size_of::<T>();
|
||||
|
||||
// SAFETY: This is just an inlined `p.addr()` (which is not
|
||||
// a `const fn` so we cannot call it).
|
||||
// During const eval, we hook this function to ensure that the pointer never
|
||||
// has provenance, making this sound.
|
||||
let addr: usize = unsafe { mem::transmute(p) };
|
||||
let addr: usize = p.addr();
|
||||
|
||||
// SAFETY: `a` is a power-of-two, therefore non-zero.
|
||||
let a_minus_one = unsafe { unchecked_sub(a, 1) };
|
||||
|
@ -1,6 +1,5 @@
|
||||
use super::*;
|
||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::mem::SizedTypeProperties;
|
||||
use crate::slice::{self, SliceIndex};
|
||||
|
||||
@ -225,7 +224,6 @@ pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self {
|
||||
///
|
||||
/// The pointer can be later reconstructed with [`from_raw_parts_mut`].
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[inline]
|
||||
pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
|
||||
(self.cast(), super::metadata(self))
|
||||
@ -306,7 +304,6 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
|
||||
/// ```
|
||||
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
|
||||
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
|
||||
@ -659,7 +656,6 @@ pub fn mask(self, mask: usize) -> *mut T {
|
||||
/// ```
|
||||
// FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized.
|
||||
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T {
|
||||
@ -1639,8 +1635,7 @@ pub unsafe fn replace(self, src: T) -> T
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "align_offset", since = "1.36.0")]
|
||||
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
|
||||
pub const fn align_offset(self, align: usize) -> usize
|
||||
pub fn align_offset(self, align: usize) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1678,95 +1673,10 @@ pub const fn align_offset(self, align: usize) -> usize
|
||||
/// assert!(ptr.is_aligned());
|
||||
/// assert!(!ptr.wrapping_byte_add(1).is_aligned());
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// is never aligned if cast to a type with a stricter alignment than the reference's
|
||||
/// underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let mut data = AlignedI32(42);
|
||||
/// let ptr = &mut data as *mut AlignedI32;
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
|
||||
/// assert!(!ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// // Also, note that mutable references are not allowed in the final value of constants.
|
||||
/// const COMPTIME_PTR: *mut AlignedI32 = (&AlignedI32(42) as *const AlignedI32).cast_mut();
|
||||
/// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.cast::<AlignedI64>().is_aligned(),
|
||||
/// runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = 40 as *mut AlignedI32;
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // For pointers with a known address, runtime and compiletime behavior are identical.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
|
||||
/// assert!(ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "pointer_is_aligned", since = "1.79.0")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned(self) -> bool
|
||||
pub fn is_aligned(self) -> bool
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1803,106 +1713,15 @@ pub const fn is_aligned(self) -> bool
|
||||
///
|
||||
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// cannot be stricter aligned than the reference's underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let mut data = AlignedI32(42);
|
||||
/// let ptr = &mut data as *mut AlignedI32;
|
||||
///
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
///
|
||||
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
|
||||
/// assert!(!ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// // Also, note that mutable references are not allowed in the final value of constants.
|
||||
/// const COMPTIME_PTR: *mut AlignedI32 = (&AlignedI32(42) as *const AlignedI32).cast_mut();
|
||||
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.is_aligned_to(8),
|
||||
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = 40 as *mut u8;
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
/// assert!(ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.is_aligned_to(16));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned_to(self, align: usize) -> bool {
|
||||
pub fn is_aligned_to(self, align: usize) -> bool {
|
||||
if !align.is_power_of_two() {
|
||||
panic!("is_aligned_to: align is not a power-of-two");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn runtime_impl(ptr: *mut (), align: usize) -> bool {
|
||||
ptr.addr() & (align - 1) == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
const fn const_impl(ptr: *mut (), align: usize) -> bool {
|
||||
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
||||
ptr.align_offset(align) == 0
|
||||
}
|
||||
|
||||
// The cast to `()` is used to
|
||||
// 1. deal with fat pointers; and
|
||||
// 2. ensure that `align_offset` (in `const_impl`) doesn't actually try to compute an offset.
|
||||
const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
|
||||
self.addr() & (align - 1) == 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -2059,7 +1878,6 @@ pub unsafe fn split_at_mut_unchecked(self, mid: usize) -> (*mut [T], *mut [T]) {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
pub const fn as_mut_ptr(self) -> *mut T {
|
||||
self as *mut T
|
||||
}
|
||||
@ -2215,7 +2033,6 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_mut_ptr(self) -> *mut T {
|
||||
self as *mut T
|
||||
}
|
||||
@ -2236,7 +2053,6 @@ pub const fn as_mut_ptr(self) -> *mut T {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
#[rustc_const_unstable(feature = "array_ptr_get", issue = "119834")]
|
||||
pub const fn as_mut_slice(self) -> *mut [T] {
|
||||
self
|
||||
}
|
||||
|
@ -131,7 +131,6 @@ pub const fn dangling() -> Self {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit<T> {
|
||||
// SAFETY: the caller must guarantee that `self` meets all the
|
||||
// requirements for a reference.
|
||||
@ -155,7 +154,6 @@ pub const fn dangling() -> Self {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit<T> {
|
||||
// SAFETY: the caller must guarantee that `self` meets all the
|
||||
// requirements for a reference.
|
||||
@ -230,7 +228,6 @@ pub const fn new(ptr: *mut T) -> Option<Self> {
|
||||
|
||||
/// Converts a reference to a `NonNull` pointer.
|
||||
#[unstable(feature = "non_null_from_ref", issue = "130823")]
|
||||
#[rustc_const_unstable(feature = "non_null_from_ref", issue = "130823")]
|
||||
#[inline]
|
||||
pub const fn from_ref(r: &T) -> Self {
|
||||
// SAFETY: A reference cannot be null.
|
||||
@ -239,7 +236,6 @@ pub const fn from_ref(r: &T) -> Self {
|
||||
|
||||
/// Converts a mutable reference to a `NonNull` pointer.
|
||||
#[unstable(feature = "non_null_from_ref", issue = "130823")]
|
||||
#[rustc_const_unstable(feature = "non_null_from_ref", issue = "130823")]
|
||||
#[inline]
|
||||
pub const fn from_mut(r: &mut T) -> Self {
|
||||
// SAFETY: A mutable reference cannot be null.
|
||||
@ -253,7 +249,6 @@ pub const fn from_mut(r: &mut T) -> Self {
|
||||
///
|
||||
/// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts(
|
||||
data_pointer: NonNull<()>,
|
||||
@ -269,7 +264,6 @@ pub const fn from_raw_parts(
|
||||
///
|
||||
/// The pointer can be later reconstructed with [`NonNull::from_raw_parts`].
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
@ -1198,8 +1192,7 @@ pub unsafe fn replace(self, src: T) -> T
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
|
||||
pub const fn align_offset(self, align: usize) -> usize
|
||||
pub fn align_offset(self, align: usize) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1230,98 +1223,10 @@ pub const fn align_offset(self, align: usize) -> usize
|
||||
/// assert!(ptr.is_aligned());
|
||||
/// assert!(!NonNull::new(ptr.as_ptr().wrapping_byte_add(1)).unwrap().is_aligned());
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// is never aligned if cast to a type with a stricter alignment than the reference's
|
||||
/// underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_nonnull_new)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let data = [AlignedI32(42), AlignedI32(42)];
|
||||
/// let ptr = NonNull::<AlignedI32>::new(&data[0] as *const _ as *mut _).unwrap();
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = unsafe { ptr.add(1).cast::<AlignedI64>() };
|
||||
/// assert!(!ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
|
||||
/// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.cast::<AlignedI64>().is_aligned(),
|
||||
/// runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
/// #![feature(const_nonnull_new)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// // On some platforms, the alignment of primitives is less than their size.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
/// #[repr(align(8))]
|
||||
/// struct AlignedI64(i64);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = NonNull::new(40 as *mut AlignedI32).unwrap();
|
||||
/// assert!(ptr.is_aligned());
|
||||
///
|
||||
/// // For pointers with a known address, runtime and compiletime behavior are identical.
|
||||
/// let ptr1 = ptr.cast::<AlignedI64>();
|
||||
/// let ptr2 = NonNull::new(ptr.as_ptr().wrapping_add(1)).unwrap().cast::<AlignedI64>();
|
||||
/// assert!(ptr1.is_aligned());
|
||||
/// assert!(!ptr2.is_aligned());
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "pointer_is_aligned", since = "1.79.0")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned(self) -> bool
|
||||
pub fn is_aligned(self) -> bool
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
@ -1358,85 +1263,10 @@ pub const fn is_aligned(self) -> bool
|
||||
///
|
||||
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// ```
|
||||
///
|
||||
/// # At compiletime
|
||||
/// **Note: Alignment at compiletime is experimental and subject to change. See the
|
||||
/// [tracking issue] for details.**
|
||||
///
|
||||
/// At compiletime, the compiler may not know where a value will end up in memory.
|
||||
/// Calling this function on a pointer created from a reference at compiletime will only
|
||||
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
|
||||
/// cannot be stricter aligned than the reference's underlying allocation.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let data = AlignedI32(42);
|
||||
/// let ptr = &data as *const AlignedI32;
|
||||
///
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
///
|
||||
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
|
||||
/// assert!(!ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
|
||||
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// // On some platforms, the alignment of i32 is less than 4.
|
||||
/// #[repr(align(4))]
|
||||
/// struct AlignedI32(i32);
|
||||
///
|
||||
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
|
||||
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
|
||||
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
|
||||
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
|
||||
///
|
||||
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
|
||||
/// let runtime_ptr = COMPTIME_PTR;
|
||||
/// assert_ne!(
|
||||
/// runtime_ptr.is_aligned_to(8),
|
||||
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// If a pointer is created from a fixed address, this function behaves the same during
|
||||
/// runtime and compiletime.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(pointer_is_aligned_to)]
|
||||
/// #![feature(const_pointer_is_aligned)]
|
||||
///
|
||||
/// const _: () = {
|
||||
/// let ptr = 40 as *const u8;
|
||||
/// assert!(ptr.is_aligned_to(1));
|
||||
/// assert!(ptr.is_aligned_to(2));
|
||||
/// assert!(ptr.is_aligned_to(4));
|
||||
/// assert!(ptr.is_aligned_to(8));
|
||||
/// assert!(!ptr.is_aligned_to(16));
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
|
||||
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||
pub const fn is_aligned_to(self, align: usize) -> bool {
|
||||
pub fn is_aligned_to(self, align: usize) -> bool {
|
||||
self.pointer.is_aligned_to(align)
|
||||
}
|
||||
}
|
||||
@ -1545,7 +1375,6 @@ pub const fn as_non_null_ptr(self) -> NonNull<T> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||
#[rustc_never_returns_null_ptr]
|
||||
pub const fn as_mut_ptr(self) -> *mut T {
|
||||
self.as_non_null_ptr().as_ptr()
|
||||
@ -1591,7 +1420,6 @@ pub const fn as_mut_ptr(self) -> *mut T {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit<T>] {
|
||||
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
|
||||
unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
|
||||
@ -1656,7 +1484,6 @@ pub const fn as_mut_ptr(self) -> *mut T {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit<T>] {
|
||||
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
|
||||
unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
|
||||
|
@ -3,6 +3,7 @@
|
||||
use core::ascii::EscapeDefault;
|
||||
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::{ascii, iter, mem, ops};
|
||||
|
||||
#[cfg(not(test))]
|
||||
@ -346,89 +347,93 @@ pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool {
|
||||
/// If any of these loads produces something for which `contains_nonascii`
|
||||
/// (above) returns true, then we know the answer is false.
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_raw_ptr_comparison, const_pointer_is_aligned)] // only in a debug assertion
|
||||
#[rustc_allow_const_fn_unstable(const_align_offset)] // behavior does not change when `align_offset` fails
|
||||
#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
|
||||
const fn is_ascii(s: &[u8]) -> bool {
|
||||
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
||||
// The runtime version behaves the same as the compiletime version, it's
|
||||
// just more optimized.
|
||||
return const_eval_select((s,), compiletime, runtime);
|
||||
|
||||
let len = s.len();
|
||||
let align_offset = s.as_ptr().align_offset(USIZE_SIZE);
|
||||
|
||||
// If we wouldn't gain anything from the word-at-a-time implementation, fall
|
||||
// back to a scalar loop.
|
||||
//
|
||||
// We also do this for architectures where `size_of::<usize>()` isn't
|
||||
// sufficient alignment for `usize`, because it's a weird edge case.
|
||||
if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() {
|
||||
return is_ascii_simple(s);
|
||||
const fn compiletime(s: &[u8]) -> bool {
|
||||
is_ascii_simple(s)
|
||||
}
|
||||
|
||||
// We always read the first word unaligned, which means `align_offset` is
|
||||
// 0, we'd read the same value again for the aligned read.
|
||||
let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset };
|
||||
#[inline]
|
||||
fn runtime(s: &[u8]) -> bool {
|
||||
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
||||
|
||||
let start = s.as_ptr();
|
||||
// SAFETY: We verify `len < USIZE_SIZE` above.
|
||||
let first_word = unsafe { (start as *const usize).read_unaligned() };
|
||||
let len = s.len();
|
||||
let align_offset = s.as_ptr().align_offset(USIZE_SIZE);
|
||||
|
||||
if contains_nonascii(first_word) {
|
||||
return false;
|
||||
}
|
||||
// We checked this above, somewhat implicitly. Note that `offset_to_aligned`
|
||||
// is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked
|
||||
// above.
|
||||
debug_assert!(offset_to_aligned <= len);
|
||||
|
||||
// SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
|
||||
// middle chunk of the slice.
|
||||
let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
|
||||
|
||||
// `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
|
||||
let mut byte_pos = offset_to_aligned;
|
||||
|
||||
// Paranoia check about alignment, since we're about to do a bunch of
|
||||
// unaligned loads. In practice this should be impossible barring a bug in
|
||||
// `align_offset` though.
|
||||
// While this method is allowed to spuriously fail in CTFE, if it doesn't
|
||||
// have alignment information it should have given a `usize::MAX` for
|
||||
// `align_offset` earlier, sending things through the scalar path instead of
|
||||
// this one, so this check should pass if it's reachable.
|
||||
debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>()));
|
||||
|
||||
// Read subsequent words until the last aligned word, excluding the last
|
||||
// aligned word by itself to be done in tail check later, to ensure that
|
||||
// tail is always one `usize` at most to extra branch `byte_pos == len`.
|
||||
while byte_pos < len - USIZE_SIZE {
|
||||
// Sanity check that the read is in bounds
|
||||
debug_assert!(byte_pos + USIZE_SIZE <= len);
|
||||
// And that our assumptions about `byte_pos` hold.
|
||||
debug_assert!(matches!(
|
||||
word_ptr.cast::<u8>().guaranteed_eq(start.wrapping_add(byte_pos)),
|
||||
// These are from the same allocation, so will hopefully always be
|
||||
// known to match even in CTFE, but if it refuses to compare them
|
||||
// that's ok since it's just a debug check anyway.
|
||||
None | Some(true),
|
||||
));
|
||||
|
||||
// SAFETY: We know `word_ptr` is properly aligned (because of
|
||||
// `align_offset`), and we know that we have enough bytes between `word_ptr` and the end
|
||||
let word = unsafe { word_ptr.read() };
|
||||
if contains_nonascii(word) {
|
||||
return false;
|
||||
// If we wouldn't gain anything from the word-at-a-time implementation, fall
|
||||
// back to a scalar loop.
|
||||
//
|
||||
// We also do this for architectures where `size_of::<usize>()` isn't
|
||||
// sufficient alignment for `usize`, because it's a weird edge case.
|
||||
if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() {
|
||||
return is_ascii_simple(s);
|
||||
}
|
||||
|
||||
byte_pos += USIZE_SIZE;
|
||||
// SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that
|
||||
// after this `add`, `word_ptr` will be at most one-past-the-end.
|
||||
word_ptr = unsafe { word_ptr.add(1) };
|
||||
// We always read the first word unaligned, which means `align_offset` is
|
||||
// 0, we'd read the same value again for the aligned read.
|
||||
let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset };
|
||||
|
||||
let start = s.as_ptr();
|
||||
// SAFETY: We verify `len < USIZE_SIZE` above.
|
||||
let first_word = unsafe { (start as *const usize).read_unaligned() };
|
||||
|
||||
if contains_nonascii(first_word) {
|
||||
return false;
|
||||
}
|
||||
// We checked this above, somewhat implicitly. Note that `offset_to_aligned`
|
||||
// is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked
|
||||
// above.
|
||||
debug_assert!(offset_to_aligned <= len);
|
||||
|
||||
// SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
|
||||
// middle chunk of the slice.
|
||||
let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
|
||||
|
||||
// `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
|
||||
let mut byte_pos = offset_to_aligned;
|
||||
|
||||
// Paranoia check about alignment, since we're about to do a bunch of
|
||||
// unaligned loads. In practice this should be impossible barring a bug in
|
||||
// `align_offset` though.
|
||||
// While this method is allowed to spuriously fail in CTFE, if it doesn't
|
||||
// have alignment information it should have given a `usize::MAX` for
|
||||
// `align_offset` earlier, sending things through the scalar path instead of
|
||||
// this one, so this check should pass if it's reachable.
|
||||
debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>()));
|
||||
|
||||
// Read subsequent words until the last aligned word, excluding the last
|
||||
// aligned word by itself to be done in tail check later, to ensure that
|
||||
// tail is always one `usize` at most to extra branch `byte_pos == len`.
|
||||
while byte_pos < len - USIZE_SIZE {
|
||||
// Sanity check that the read is in bounds
|
||||
debug_assert!(byte_pos + USIZE_SIZE <= len);
|
||||
// And that our assumptions about `byte_pos` hold.
|
||||
debug_assert!(word_ptr.cast::<u8>() == start.wrapping_add(byte_pos));
|
||||
|
||||
// SAFETY: We know `word_ptr` is properly aligned (because of
|
||||
// `align_offset`), and we know that we have enough bytes between `word_ptr` and the end
|
||||
let word = unsafe { word_ptr.read() };
|
||||
if contains_nonascii(word) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte_pos += USIZE_SIZE;
|
||||
// SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that
|
||||
// after this `add`, `word_ptr` will be at most one-past-the-end.
|
||||
word_ptr = unsafe { word_ptr.add(1) };
|
||||
}
|
||||
|
||||
// Sanity check to ensure there really is only one `usize` left. This should
|
||||
// be guaranteed by our loop condition.
|
||||
debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE);
|
||||
|
||||
// SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
|
||||
let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() };
|
||||
|
||||
!contains_nonascii(last_word)
|
||||
}
|
||||
|
||||
// Sanity check to ensure there really is only one `usize` left. This should
|
||||
// be guaranteed by our loop condition.
|
||||
debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE);
|
||||
|
||||
// SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
|
||||
let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() };
|
||||
|
||||
!contains_nonascii(last_word)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Original implementation taken from rust-memchr.
|
||||
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
|
||||
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::mem;
|
||||
|
||||
const LO_USIZE: usize = usize::repeat_u8(0x01);
|
||||
@ -50,58 +51,66 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
#[rustc_allow_const_fn_unstable(const_cmp)]
|
||||
#[rustc_allow_const_fn_unstable(const_align_offset)]
|
||||
#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
|
||||
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
|
||||
const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> {
|
||||
// Scan for a single byte value by reading two `usize` words at a time.
|
||||
//
|
||||
// Split `text` in three parts
|
||||
// - unaligned initial part, before the first word aligned address in text
|
||||
// - body, scan by 2 words at a time
|
||||
// - the last remaining part, < 2 word size
|
||||
// The runtime version behaves the same as the compiletime version, it's
|
||||
// just more optimized.
|
||||
return const_eval_select((x, text), compiletime, runtime);
|
||||
|
||||
// search up to an aligned boundary
|
||||
let len = text.len();
|
||||
let ptr = text.as_ptr();
|
||||
let mut offset = ptr.align_offset(USIZE_BYTES);
|
||||
|
||||
if offset > 0 {
|
||||
// FIXME(const-hack, fee1-dead): replace with min
|
||||
offset = if offset < len { offset } else { len };
|
||||
// FIXME(const-hack, fee1-dead): replace with range slicing
|
||||
// SAFETY: offset is within bounds
|
||||
let slice = unsafe { super::from_raw_parts(text.as_ptr(), offset) };
|
||||
if let Some(index) = memchr_naive(x, slice) {
|
||||
return Some(index);
|
||||
}
|
||||
const fn compiletime(x: u8, text: &[u8]) -> Option<usize> {
|
||||
memchr_naive(x, text)
|
||||
}
|
||||
|
||||
// search the body of the text
|
||||
let repeated_x = usize::repeat_u8(x);
|
||||
while offset <= len - 2 * USIZE_BYTES {
|
||||
// SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes
|
||||
// between the offset and the end of the slice.
|
||||
unsafe {
|
||||
let u = *(ptr.add(offset) as *const usize);
|
||||
let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
|
||||
#[inline]
|
||||
fn runtime(x: u8, text: &[u8]) -> Option<usize> {
|
||||
// Scan for a single byte value by reading two `usize` words at a time.
|
||||
//
|
||||
// Split `text` in three parts
|
||||
// - unaligned initial part, before the first word aligned address in text
|
||||
// - body, scan by 2 words at a time
|
||||
// - the last remaining part, < 2 word size
|
||||
|
||||
// break if there is a matching byte
|
||||
let zu = contains_zero_byte(u ^ repeated_x);
|
||||
let zv = contains_zero_byte(v ^ repeated_x);
|
||||
if zu || zv {
|
||||
break;
|
||||
// search up to an aligned boundary
|
||||
let len = text.len();
|
||||
let ptr = text.as_ptr();
|
||||
let mut offset = ptr.align_offset(USIZE_BYTES);
|
||||
|
||||
if offset > 0 {
|
||||
offset = offset.min(len);
|
||||
let slice = &text[..offset];
|
||||
if let Some(index) = memchr_naive(x, slice) {
|
||||
return Some(index);
|
||||
}
|
||||
}
|
||||
offset += USIZE_BYTES * 2;
|
||||
}
|
||||
|
||||
// Find the byte after the point the body loop stopped.
|
||||
// FIXME(const-hack): Use `?` instead.
|
||||
// FIXME(const-hack, fee1-dead): use range slicing
|
||||
// SAFETY: offset is within bounds
|
||||
let slice = unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) };
|
||||
if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None }
|
||||
// search the body of the text
|
||||
let repeated_x = usize::repeat_u8(x);
|
||||
while offset <= len - 2 * USIZE_BYTES {
|
||||
// SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes
|
||||
// between the offset and the end of the slice.
|
||||
unsafe {
|
||||
let u = *(ptr.add(offset) as *const usize);
|
||||
let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
|
||||
|
||||
// break if there is a matching byte
|
||||
let zu = contains_zero_byte(u ^ repeated_x);
|
||||
let zv = contains_zero_byte(v ^ repeated_x);
|
||||
if zu || zv {
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset += USIZE_BYTES * 2;
|
||||
}
|
||||
|
||||
// Find the byte after the point the body loop stopped.
|
||||
// FIXME(const-hack): Use `?` instead.
|
||||
// FIXME(const-hack, fee1-dead): use range slicing
|
||||
let slice =
|
||||
// SAFETY: offset is within bounds
|
||||
unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) };
|
||||
if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last index matching the byte `x` in `text`.
|
||||
|
@ -82,7 +82,6 @@
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
|
||||
#[rustc_allow_const_fn_unstable(str_internals)]
|
||||
#[rustc_diagnostic_item = "str_from_utf8"]
|
||||
pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
|
||||
// FIXME(const-hack): This should use `?` again, once it's `const`
|
||||
@ -218,7 +217,6 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
|
||||
#[rustc_const_unstable(feature = "str_from_raw_parts", issue = "119206")]
|
||||
pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str {
|
||||
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
|
||||
unsafe { &*ptr::from_raw_parts(ptr, len) }
|
||||
@ -237,7 +235,6 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
|
||||
#[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")]
|
||||
pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut str {
|
||||
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
|
||||
unsafe { &mut *ptr::from_raw_parts_mut(ptr, len) }
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Operations related to UTF-8 validation.
|
||||
|
||||
use super::Utf8Error;
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::mem;
|
||||
|
||||
/// Returns the initial codepoint accumulator for the first byte.
|
||||
@ -122,15 +123,28 @@ const fn contains_nonascii(x: usize) -> bool {
|
||||
/// Walks through `v` checking that it's a valid UTF-8 sequence,
|
||||
/// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`.
|
||||
#[inline(always)]
|
||||
#[rustc_const_unstable(feature = "str_internals", issue = "none")]
|
||||
#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
|
||||
pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
|
||||
let mut index = 0;
|
||||
let len = v.len();
|
||||
|
||||
let usize_bytes = mem::size_of::<usize>();
|
||||
let ascii_block_size = 2 * usize_bytes;
|
||||
const USIZE_BYTES: usize = mem::size_of::<usize>();
|
||||
|
||||
let ascii_block_size = 2 * USIZE_BYTES;
|
||||
let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 };
|
||||
let align = v.as_ptr().align_offset(usize_bytes);
|
||||
let align = {
|
||||
const fn compiletime(_v: &[u8]) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
|
||||
fn runtime(v: &[u8]) -> usize {
|
||||
v.as_ptr().align_offset(USIZE_BYTES)
|
||||
}
|
||||
|
||||
// Below, we safely fall back to a slower codepath if the offset is `usize::MAX`,
|
||||
// so the end-to-end behavior is the same at compiletime and runtime.
|
||||
const_eval_select((v,), compiletime, runtime)
|
||||
};
|
||||
|
||||
while index < len {
|
||||
let old_offset = index;
|
||||
@ -209,11 +223,11 @@ macro_rules! next {
|
||||
// Ascii case, try to skip forward quickly.
|
||||
// When the pointer is aligned, read 2 words of data per iteration
|
||||
// until we find a word containing a non-ascii byte.
|
||||
if align != usize::MAX && align.wrapping_sub(index) % usize_bytes == 0 {
|
||||
if align != usize::MAX && align.wrapping_sub(index) % USIZE_BYTES == 0 {
|
||||
let ptr = v.as_ptr();
|
||||
while index < blocks_end {
|
||||
// SAFETY: since `align - index` and `ascii_block_size` are
|
||||
// multiples of `usize_bytes`, `block = ptr.add(index)` is
|
||||
// multiples of `USIZE_BYTES`, `block = ptr.add(index)` is
|
||||
// always aligned with a `usize` so it's safe to dereference
|
||||
// both `block` and `block.add(1)`.
|
||||
unsafe {
|
||||
|
@ -130,7 +130,6 @@ pub const fn get_mut(&mut self) -> &mut T {
|
||||
/// access to the underlying value, but _pinned_ `Exclusive`s only
|
||||
/// produce _pinned_ access to the underlying value.
|
||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||
#[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
|
||||
@ -154,7 +153,6 @@ pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
|
||||
/// a _pinned mutable_ reference to a `T`. This allows you to skip
|
||||
/// building an `Exclusive` with [`Exclusive::new`].
|
||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||
#[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
|
||||
|
@ -253,7 +253,6 @@ pub const fn waker(&self) -> &'a Waker {
|
||||
/// Returns a reference to the [`LocalWaker`] for the current task.
|
||||
#[inline]
|
||||
#[unstable(feature = "local_waker", issue = "118959")]
|
||||
#[rustc_const_unstable(feature = "local_waker", issue = "118959")]
|
||||
pub const fn local_waker(&self) -> &'a LocalWaker {
|
||||
&self.local_waker
|
||||
}
|
||||
@ -261,7 +260,6 @@ pub const fn local_waker(&self) -> &'a LocalWaker {
|
||||
/// Returns a reference to the extension data for the current task.
|
||||
#[inline]
|
||||
#[unstable(feature = "context_ext", issue = "123392")]
|
||||
#[rustc_const_unstable(feature = "context_ext", issue = "123392")]
|
||||
pub const fn ext(&mut self) -> &mut dyn Any {
|
||||
// FIXME: this field makes Context extra-weird about unwind safety
|
||||
// can we justify AssertUnwindSafe if we stabilize this? do we care?
|
||||
@ -337,7 +335,6 @@ pub const fn from_waker(waker: &'a Waker) -> Self {
|
||||
/// Creates a ContextBuilder from an existing Context.
|
||||
#[inline]
|
||||
#[unstable(feature = "context_ext", issue = "123392")]
|
||||
#[rustc_const_unstable(feature = "context_ext", issue = "123392")]
|
||||
pub const fn from(cx: &'a mut Context<'_>) -> Self {
|
||||
let ext = match &mut cx.ext.0 {
|
||||
ExtData::Some(ext) => ExtData::Some(*ext),
|
||||
@ -355,7 +352,6 @@ pub const fn from(cx: &'a mut Context<'_>) -> Self {
|
||||
/// Sets the value for the waker on `Context`.
|
||||
#[inline]
|
||||
#[unstable(feature = "context_ext", issue = "123392")]
|
||||
#[rustc_const_unstable(feature = "context_ext", issue = "123392")]
|
||||
pub const fn waker(self, waker: &'a Waker) -> Self {
|
||||
Self { waker, ..self }
|
||||
}
|
||||
@ -363,7 +359,6 @@ pub const fn waker(self, waker: &'a Waker) -> Self {
|
||||
/// Sets the value for the local waker on `Context`.
|
||||
#[inline]
|
||||
#[unstable(feature = "local_waker", issue = "118959")]
|
||||
#[rustc_const_unstable(feature = "local_waker", issue = "118959")]
|
||||
pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self {
|
||||
Self { local_waker, ..self }
|
||||
}
|
||||
@ -371,7 +366,6 @@ pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self {
|
||||
/// Sets the value for the extension data on `Context`.
|
||||
#[inline]
|
||||
#[unstable(feature = "context_ext", issue = "123392")]
|
||||
#[rustc_const_unstable(feature = "context_ext", issue = "123392")]
|
||||
pub const fn ext(self, data: &'a mut dyn Any) -> Self {
|
||||
Self { ext: ExtData::Some(data), ..self }
|
||||
}
|
||||
@ -834,7 +828,6 @@ pub fn will_wake(&self, other: &LocalWaker) -> bool {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "local_waker", issue = "118959")]
|
||||
#[rustc_const_unstable(feature = "local_waker", issue = "118959")]
|
||||
pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker {
|
||||
Self { waker }
|
||||
}
|
||||
|
@ -883,7 +883,6 @@ pub const fn as_secs_f32(&self) -> f32 {
|
||||
#[unstable(feature = "duration_millis_float", issue = "122451")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")]
|
||||
pub const fn as_millis_f64(&self) -> f64 {
|
||||
(self.secs as f64) * (MILLIS_PER_SEC as f64)
|
||||
+ (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64)
|
||||
@ -904,7 +903,6 @@ pub const fn as_millis_f64(&self) -> f64 {
|
||||
#[unstable(feature = "duration_millis_float", issue = "122451")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")]
|
||||
pub const fn as_millis_f32(&self) -> f32 {
|
||||
(self.secs as f32) * (MILLIS_PER_SEC as f32)
|
||||
+ (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32)
|
||||
|
@ -120,7 +120,19 @@ const fn comptime() -> bool {
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
||||
pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool {
|
||||
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
|
||||
#[inline]
|
||||
fn runtime(ptr: *const (), align: usize, is_zst: bool) -> bool {
|
||||
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
||||
const fn comptime(ptr: *const (), _align: usize, is_zst: bool) -> bool {
|
||||
is_zst || !ptr.is_null()
|
||||
}
|
||||
|
||||
// This is just for safety checks so we can const_eval_select.
|
||||
const_eval_select((ptr, align, is_zst), comptime, runtime)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1,6 +1,5 @@
|
||||
///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
|
||||
|
||||
#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
|
||||
#[inline(always)]
|
||||
const fn bitset_search<
|
||||
const N: usize,
|
||||
@ -424,7 +423,6 @@ pub mod lowercase {
|
||||
(5, 187), (6, 78), (7, 132),
|
||||
];
|
||||
|
||||
#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
|
||||
pub const fn lookup(c: char) -> bool {
|
||||
super::bitset_search(
|
||||
c as u32,
|
||||
@ -549,7 +547,6 @@ pub mod uppercase {
|
||||
(2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171),
|
||||
];
|
||||
|
||||
#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
|
||||
pub const fn lookup(c: char) -> bool {
|
||||
super::bitset_search(
|
||||
c as u32,
|
||||
|
@ -16,17 +16,13 @@
|
||||
#![feature(cell_update)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(const_align_of_val_raw)]
|
||||
#![feature(const_align_offset)]
|
||||
#![feature(const_bigint_helper_methods)]
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_hash)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_nonnull_new)]
|
||||
#![feature(const_num_midpoint)]
|
||||
#![feature(const_option_ext)]
|
||||
#![feature(const_pin_2)]
|
||||
#![feature(const_pointer_is_aligned)]
|
||||
#![feature(const_three_way_compare)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
@ -359,22 +359,6 @@ fn align_offset_zst() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_zst_const() {
|
||||
const {
|
||||
// For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
|
||||
// all, because no amount of elements will align the pointer.
|
||||
let mut p = 1;
|
||||
while p < 1024 {
|
||||
assert!(ptr::without_provenance::<()>(p).align_offset(p) == 0);
|
||||
if p != 1 {
|
||||
assert!(ptr::without_provenance::<()>(p + 1).align_offset(p) == !0);
|
||||
}
|
||||
p = (p + 1).next_power_of_two();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_stride_one() {
|
||||
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
|
||||
@ -396,25 +380,6 @@ fn align_offset_stride_one() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_stride_one_const() {
|
||||
const {
|
||||
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
|
||||
// number of bytes.
|
||||
let mut align = 1;
|
||||
while align < 1024 {
|
||||
let mut ptr = 1;
|
||||
while ptr < 2 * align {
|
||||
let expected = ptr % align;
|
||||
let offset = if expected == 0 { 0 } else { align - expected };
|
||||
assert!(ptr::without_provenance::<u8>(ptr).align_offset(align) == offset);
|
||||
ptr += 1;
|
||||
}
|
||||
align = (align + 1).next_power_of_two();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_various_strides() {
|
||||
unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
|
||||
@ -495,192 +460,6 @@ struct A10(
|
||||
assert!(!x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_various_strides_const() {
|
||||
const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
|
||||
let mut expected = usize::MAX;
|
||||
// Naive but definitely correct way to find the *first* aligned element of stride::<T>.
|
||||
let mut el = 0;
|
||||
while el < align {
|
||||
if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
|
||||
expected = el;
|
||||
break;
|
||||
}
|
||||
el += 1;
|
||||
}
|
||||
let got = ptr.align_offset(align);
|
||||
assert!(got == expected);
|
||||
}
|
||||
|
||||
const {
|
||||
// For pointers of stride != 1, we verify the algorithm against the naivest possible
|
||||
// implementation
|
||||
let mut align = 1;
|
||||
let limit = 32;
|
||||
while align < limit {
|
||||
let mut ptr = 1;
|
||||
while ptr < 4 * align {
|
||||
unsafe {
|
||||
#[repr(packed)]
|
||||
struct A3(#[allow(dead_code)] u16, #[allow(dead_code)] u8);
|
||||
test_stride::<A3>(ptr::without_provenance::<A3>(ptr), ptr, align);
|
||||
|
||||
struct A4(#[allow(dead_code)] u32);
|
||||
test_stride::<A4>(ptr::without_provenance::<A4>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A5(#[allow(dead_code)] u32, #[allow(dead_code)] u8);
|
||||
test_stride::<A5>(ptr::without_provenance::<A5>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A6(#[allow(dead_code)] u32, #[allow(dead_code)] u16);
|
||||
test_stride::<A6>(ptr::without_provenance::<A6>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A7(
|
||||
#[allow(dead_code)] u32,
|
||||
#[allow(dead_code)] u16,
|
||||
#[allow(dead_code)] u8,
|
||||
);
|
||||
test_stride::<A7>(ptr::without_provenance::<A7>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A8(#[allow(dead_code)] u32, #[allow(dead_code)] u32);
|
||||
test_stride::<A8>(ptr::without_provenance::<A8>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A9(
|
||||
#[allow(dead_code)] u32,
|
||||
#[allow(dead_code)] u32,
|
||||
#[allow(dead_code)] u8,
|
||||
);
|
||||
test_stride::<A9>(ptr::without_provenance::<A9>(ptr), ptr, align);
|
||||
|
||||
#[repr(packed)]
|
||||
struct A10(
|
||||
#[allow(dead_code)] u32,
|
||||
#[allow(dead_code)] u32,
|
||||
#[allow(dead_code)] u16,
|
||||
);
|
||||
test_stride::<A10>(ptr::without_provenance::<A10>(ptr), ptr, align);
|
||||
|
||||
test_stride::<u32>(ptr::without_provenance::<u32>(ptr), ptr, align);
|
||||
test_stride::<u128>(ptr::without_provenance::<u128>(ptr), ptr, align);
|
||||
}
|
||||
ptr += 1;
|
||||
}
|
||||
align = (align + 1).next_power_of_two();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_with_provenance_const() {
|
||||
const {
|
||||
// On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4.
|
||||
#[repr(align(4))]
|
||||
struct AlignedI32(i32);
|
||||
|
||||
let data = AlignedI32(42);
|
||||
|
||||
// `stride % align == 0` (usual case)
|
||||
|
||||
let ptr: *const i32 = &data.0;
|
||||
assert!(ptr.align_offset(1) == 0);
|
||||
assert!(ptr.align_offset(2) == 0);
|
||||
assert!(ptr.align_offset(4) == 0);
|
||||
assert!(ptr.align_offset(8) == usize::MAX);
|
||||
assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
|
||||
assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
|
||||
assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
|
||||
assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
|
||||
assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
|
||||
assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
|
||||
|
||||
assert!(ptr.wrapping_add(42).align_offset(4) == 0);
|
||||
assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
|
||||
|
||||
let ptr1: *const i8 = ptr.cast();
|
||||
assert!(ptr1.align_offset(1) == 0);
|
||||
assert!(ptr1.align_offset(2) == 0);
|
||||
assert!(ptr1.align_offset(4) == 0);
|
||||
assert!(ptr1.align_offset(8) == usize::MAX);
|
||||
assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
|
||||
assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
|
||||
assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
|
||||
assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
|
||||
assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
|
||||
assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
|
||||
assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
|
||||
assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
|
||||
assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
|
||||
assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
|
||||
assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
|
||||
|
||||
let ptr2: *const i16 = ptr.cast();
|
||||
assert!(ptr2.align_offset(1) == 0);
|
||||
assert!(ptr2.align_offset(2) == 0);
|
||||
assert!(ptr2.align_offset(4) == 0);
|
||||
assert!(ptr2.align_offset(8) == usize::MAX);
|
||||
assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
|
||||
assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
|
||||
assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
|
||||
assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
|
||||
assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
|
||||
assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
|
||||
assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
|
||||
|
||||
let ptr3: *const i64 = ptr.cast();
|
||||
assert!(ptr3.align_offset(1) == 0);
|
||||
assert!(ptr3.align_offset(2) == 0);
|
||||
assert!(ptr3.align_offset(4) == 0);
|
||||
assert!(ptr3.align_offset(8) == usize::MAX);
|
||||
assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
|
||||
|
||||
// `stride % align != 0` (edge case)
|
||||
|
||||
let ptr4: *const [u8; 3] = ptr.cast();
|
||||
assert!(ptr4.align_offset(1) == 0);
|
||||
assert!(ptr4.align_offset(2) == 0);
|
||||
assert!(ptr4.align_offset(4) == 0);
|
||||
assert!(ptr4.align_offset(8) == usize::MAX);
|
||||
assert!(ptr4.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr4.wrapping_byte_add(1).align_offset(2) == 1);
|
||||
assert!(ptr4.wrapping_byte_add(1).align_offset(4) == 1);
|
||||
assert!(ptr4.wrapping_byte_add(1).align_offset(8) == usize::MAX);
|
||||
assert!(ptr4.wrapping_byte_add(2).align_offset(1) == 0);
|
||||
assert!(ptr4.wrapping_byte_add(2).align_offset(2) == 0);
|
||||
assert!(ptr4.wrapping_byte_add(2).align_offset(4) == 2);
|
||||
assert!(ptr4.wrapping_byte_add(2).align_offset(8) == usize::MAX);
|
||||
assert!(ptr4.wrapping_byte_add(3).align_offset(1) == 0);
|
||||
assert!(ptr4.wrapping_byte_add(3).align_offset(2) == 1);
|
||||
assert!(ptr4.wrapping_byte_add(3).align_offset(4) == 3);
|
||||
assert!(ptr4.wrapping_byte_add(3).align_offset(8) == usize::MAX);
|
||||
|
||||
let ptr5: *const [u8; 5] = ptr.cast();
|
||||
assert!(ptr5.align_offset(1) == 0);
|
||||
assert!(ptr5.align_offset(2) == 0);
|
||||
assert!(ptr5.align_offset(4) == 0);
|
||||
assert!(ptr5.align_offset(8) == usize::MAX);
|
||||
assert!(ptr5.wrapping_byte_add(1).align_offset(1) == 0);
|
||||
assert!(ptr5.wrapping_byte_add(1).align_offset(2) == 1);
|
||||
assert!(ptr5.wrapping_byte_add(1).align_offset(4) == 3);
|
||||
assert!(ptr5.wrapping_byte_add(1).align_offset(8) == usize::MAX);
|
||||
assert!(ptr5.wrapping_byte_add(2).align_offset(1) == 0);
|
||||
assert!(ptr5.wrapping_byte_add(2).align_offset(2) == 0);
|
||||
assert!(ptr5.wrapping_byte_add(2).align_offset(4) == 2);
|
||||
assert!(ptr5.wrapping_byte_add(2).align_offset(8) == usize::MAX);
|
||||
assert!(ptr5.wrapping_byte_add(3).align_offset(1) == 0);
|
||||
assert!(ptr5.wrapping_byte_add(3).align_offset(2) == 1);
|
||||
assert!(ptr5.wrapping_byte_add(3).align_offset(4) == 1);
|
||||
assert!(ptr5.wrapping_byte_add(3).align_offset(8) == usize::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_issue_103361() {
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
@ -693,23 +472,6 @@ fn align_offset_issue_103361() {
|
||||
let _ = ptr::without_provenance::<HugeSize>(SIZE).align_offset(SIZE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_offset_issue_103361_const() {
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const SIZE: usize = 1 << 47;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const SIZE: usize = 1 << 30;
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
const SIZE: usize = 1 << 13;
|
||||
struct HugeSize(#[allow(dead_code)] [u8; SIZE - 1]);
|
||||
|
||||
const {
|
||||
assert!(ptr::without_provenance::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
|
||||
assert!(ptr::without_provenance::<HugeSize>(SIZE).align_offset(SIZE) == 0);
|
||||
assert!(ptr::without_provenance::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_aligned() {
|
||||
let data = 42;
|
||||
@ -726,25 +488,6 @@ fn is_aligned() {
|
||||
assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_aligned_const() {
|
||||
const {
|
||||
let data = 42;
|
||||
let ptr: *const i32 = &data;
|
||||
assert!(ptr.is_aligned());
|
||||
assert!(ptr.is_aligned_to(1));
|
||||
assert!(ptr.is_aligned_to(2));
|
||||
assert!(ptr.is_aligned_to(4));
|
||||
assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
|
||||
assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
|
||||
assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
|
||||
|
||||
// At comptime neither `ptr` nor `ptr+1` is aligned to 8.
|
||||
assert!(!ptr.is_aligned_to(8));
|
||||
assert!(!ptr.wrapping_add(1).is_aligned_to(8));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offset_from() {
|
||||
let mut a = [0; 5];
|
||||
|
@ -256,7 +256,8 @@ The valid types of print values are:
|
||||
- `crate-name` — The name of the crate.
|
||||
- `file-names` — The names of the files created by the `link` emit kind.
|
||||
- `sysroot` — Path to the sysroot.
|
||||
- `target-libdir` - Path to the target libdir.
|
||||
- `target-libdir` — Path to the target libdir.
|
||||
- `host-tuple` — The target-tuple string of the host compiler (e.g. `x86_64-unknown-linux-gnu`)
|
||||
- `cfg` — List of cfg values. See [conditional compilation] for more
|
||||
information about cfg values.
|
||||
- `target-list` — List of known targets. The target may be selected with the
|
||||
@ -286,7 +287,7 @@ The valid types of print values are:
|
||||
exact format of this debugging output is not a stable guarantee, other than
|
||||
that it will include the linker executable and the text of each command-line
|
||||
argument passed to the linker.
|
||||
- `deployment-target` - The currently selected [deployment target] (or minimum OS version)
|
||||
- `deployment-target` — The currently selected [deployment target] (or minimum OS version)
|
||||
for the selected Apple platform target. This value can be used or passed along to other
|
||||
components alongside a Rust build that need this information, such as C compilers.
|
||||
This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable
|
||||
|
@ -52,7 +52,7 @@ rustdoc 1.17.0 (56124baa9 2017-04-24)
|
||||
binary: rustdoc
|
||||
commit-hash: hash
|
||||
commit-date: date
|
||||
host: host-triple
|
||||
host: host-tuple
|
||||
release: 1.17.0
|
||||
LLVM version: 3.9
|
||||
```
|
||||
|
@ -17,7 +17,7 @@
|
||||
use rustc_session::{EarlyDiagCtxt, getopts};
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_target::spec::TargetTriple;
|
||||
use rustc_target::spec::TargetTuple;
|
||||
|
||||
use crate::core::new_dcx;
|
||||
use crate::externalfiles::ExternalHtml;
|
||||
@ -96,7 +96,7 @@ pub(crate) struct Options {
|
||||
/// Unstable (`-Z`) options strings to pass to the compiler.
|
||||
pub(crate) unstable_opts_strs: Vec<String>,
|
||||
/// The target used to compile the crate against.
|
||||
pub(crate) target: TargetTriple,
|
||||
pub(crate) target: TargetTuple,
|
||||
/// Edition used when reading the crate. Defaults to "2015". Also used by default when
|
||||
/// compiling doctests from the crate.
|
||||
pub(crate) edition: Edition,
|
||||
|
@ -24,7 +24,7 @@
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use rustc_target::spec::{Target, TargetTuple};
|
||||
use tempfile::{Builder as TempFileBuilder, TempDir};
|
||||
use tracing::debug;
|
||||
|
||||
@ -414,10 +414,10 @@ pub(crate) struct UnusedExterns {
|
||||
unused_extern_names: Vec<String>,
|
||||
}
|
||||
|
||||
fn add_exe_suffix(input: String, target: &TargetTriple) -> String {
|
||||
fn add_exe_suffix(input: String, target: &TargetTuple) -> String {
|
||||
let exe_suffix = match target {
|
||||
TargetTriple::TargetTriple(_) => Target::expect_builtin(target).options.exe_suffix,
|
||||
TargetTriple::TargetJson { contents, .. } => {
|
||||
TargetTuple::TargetTuple(_) => Target::expect_builtin(target).options.exe_suffix,
|
||||
TargetTuple::TargetJson { contents, .. } => {
|
||||
Target::from_json(contents.parse().unwrap()).unwrap().0.options.exe_suffix
|
||||
}
|
||||
};
|
||||
@ -513,8 +513,8 @@ fn run_test(
|
||||
compiler.arg("--emit=metadata");
|
||||
}
|
||||
compiler.arg("--target").arg(match &rustdoc_options.target {
|
||||
TargetTriple::TargetTriple(s) => s,
|
||||
TargetTriple::TargetJson { path_for_rustdoc, .. } => {
|
||||
TargetTuple::TargetTuple(s) => s,
|
||||
TargetTuple::TargetJson { path_for_rustdoc, .. } => {
|
||||
path_for_rustdoc.to_str().expect("target path must be valid unicode")
|
||||
}
|
||||
});
|
||||
|
@ -761,7 +761,7 @@ pub fn expected_output_path(
|
||||
|
||||
/// Absolute path to the directory where all output for all tests in the given
|
||||
/// `relative_dir` group should reside. Example:
|
||||
/// /path/to/build/host-triple/test/ui/relative/
|
||||
/// /path/to/build/host-tuple/test/ui/relative/
|
||||
/// This is created early when tests are collected to avoid race conditions.
|
||||
pub fn output_relative_path(config: &Config, relative_dir: &Path) -> PathBuf {
|
||||
config.build_base.join(relative_dir)
|
||||
@ -784,7 +784,7 @@ pub fn output_testname_unique(
|
||||
|
||||
/// Absolute path to the directory where all output for the given
|
||||
/// test/revision should reside. Example:
|
||||
/// /path/to/build/host-triple/test/ui/relative/testname.revision.mode/
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/
|
||||
pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
output_relative_path(config, &testpaths.relative_dir)
|
||||
.join(output_testname_unique(config, testpaths, revision))
|
||||
@ -792,13 +792,13 @@ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<
|
||||
|
||||
/// Absolute path to the base filename used as output for the given
|
||||
/// test/revision. Example:
|
||||
/// /path/to/build/host-triple/test/ui/relative/testname.revision.mode/testname
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/testname
|
||||
pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
|
||||
}
|
||||
|
||||
/// Absolute path to the directory to use for incremental compilation. Example:
|
||||
/// /path/to/build/host-triple/test/ui/relative/testname.mode/testname.inc
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.mode/testname.inc
|
||||
pub fn incremental_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
output_base_name(config, testpaths, revision).with_extension("inc")
|
||||
}
|
||||
|
@ -1825,7 +1825,7 @@ fn safe_revision(&self) -> Option<&str> {
|
||||
|
||||
/// Gets the absolute path to the directory where all output for the given
|
||||
/// test/revision should reside.
|
||||
/// E.g., `/path/to/build/host-triple/test/ui/relative/testname.revision.mode/`.
|
||||
/// E.g., `/path/to/build/host-tuple/test/ui/relative/testname.revision.mode/`.
|
||||
fn output_base_dir(&self) -> PathBuf {
|
||||
output_base_dir(self.config, self.testpaths, self.safe_revision())
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx>) -> Self {
|
||||
clock: Clock::new(config.isolated_op == IsolatedOp::Allow),
|
||||
#[cfg(unix)]
|
||||
native_lib: config.native_lib.as_ref().map(|lib_file_path| {
|
||||
let target_triple = tcx.sess.opts.target_triple.triple();
|
||||
let target_triple = tcx.sess.opts.target_triple.tuple();
|
||||
// Check if host target == the session target.
|
||||
if env!("TARGET") != target_triple {
|
||||
panic!(
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#[derive(Builder)]
|
||||
pub struct Environment {
|
||||
host_triple: String,
|
||||
host_tuple: String,
|
||||
python_binary: String,
|
||||
/// The rustc checkout, where the compiler source is located.
|
||||
checkout_dir: Utf8PathBuf,
|
||||
@ -28,8 +28,8 @@ pub struct Environment {
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
pub fn host_triple(&self) -> &str {
|
||||
&self.host_triple
|
||||
pub fn host_tuple(&self) -> &str {
|
||||
&self.host_tuple
|
||||
}
|
||||
|
||||
pub fn python_binary(&self) -> &str {
|
||||
@ -45,7 +45,7 @@ pub fn build_root(&self) -> Utf8PathBuf {
|
||||
}
|
||||
|
||||
pub fn build_artifacts(&self) -> Utf8PathBuf {
|
||||
self.build_root().join("build").join(&self.host_triple)
|
||||
self.build_root().join("build").join(&self.host_tuple)
|
||||
}
|
||||
|
||||
pub fn artifact_dir(&self) -> Utf8PathBuf {
|
||||
|
@ -105,9 +105,9 @@ pub fn build(env: &Environment) -> Self {
|
||||
env.checkout_path().join("x.py").as_str(),
|
||||
"build",
|
||||
"--target",
|
||||
&env.host_triple(),
|
||||
&env.host_tuple(),
|
||||
"--host",
|
||||
&env.host_triple(),
|
||||
&env.host_tuple(),
|
||||
"--stage",
|
||||
"2",
|
||||
"library/std",
|
||||
|
@ -127,7 +127,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
|
||||
shared,
|
||||
} => {
|
||||
let env = EnvironmentBuilder::default()
|
||||
.host_triple(target_triple)
|
||||
.host_tuple(target_triple)
|
||||
.python_binary(python)
|
||||
.checkout_dir(checkout_dir.clone())
|
||||
.host_llvm_dir(llvm_dir)
|
||||
@ -148,7 +148,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
|
||||
|
||||
let checkout_dir = Utf8PathBuf::from("/checkout");
|
||||
let env = EnvironmentBuilder::default()
|
||||
.host_triple(target_triple)
|
||||
.host_tuple(target_triple)
|
||||
.python_binary("python3".to_string())
|
||||
.checkout_dir(checkout_dir.clone())
|
||||
.host_llvm_dir(Utf8PathBuf::from("/rustroot"))
|
||||
@ -170,7 +170,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
|
||||
|
||||
let checkout_dir: Utf8PathBuf = std::env::current_dir()?.try_into()?;
|
||||
let env = EnvironmentBuilder::default()
|
||||
.host_triple(target_triple)
|
||||
.host_tuple(target_triple)
|
||||
.python_binary("python".to_string())
|
||||
.checkout_dir(checkout_dir.clone())
|
||||
.host_llvm_dir(checkout_dir.join("citools").join("clang-rust"))
|
||||
|
@ -22,7 +22,7 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
|
||||
assert!(extracted_path.is_dir());
|
||||
Ok(extracted_path)
|
||||
};
|
||||
let host_triple = env.host_triple();
|
||||
let host_triple = env.host_tuple();
|
||||
let version = find_dist_version(&dist_dir)?;
|
||||
|
||||
// Extract rustc, libstd, cargo and src archives to create the optimized sysroot
|
||||
@ -87,7 +87,7 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
|
||||
x_py.as_str(),
|
||||
"test",
|
||||
"--build",
|
||||
env.host_triple(),
|
||||
env.host_tuple(),
|
||||
"--stage",
|
||||
"0",
|
||||
"tests/assembly",
|
||||
|
@ -1,4 +1,3 @@
|
||||
#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
|
||||
#[inline(always)]
|
||||
const fn bitset_search<
|
||||
const N: usize,
|
||||
|
@ -97,11 +97,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
self.blank_line();
|
||||
|
||||
writeln!(
|
||||
&mut self.file,
|
||||
r#"#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]"#
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
|
||||
if first_code_point > 0x7f {
|
||||
writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} &&").unwrap();
|
||||
|
@ -2,8 +2,9 @@ error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{as
|
||||
--> $DIR/not-clone-closure.rs:32:15
|
||||
|
|
||||
LL | not_clone.clone();
|
||||
| ^^^^^ within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`
|
||||
| ^^^^^ unsatisfied trait bound
|
||||
|
|
||||
= help: within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`
|
||||
note: required because it's used within this closure
|
||||
--> $DIR/not-clone-closure.rs:29:21
|
||||
|
|
||||
|
@ -3,6 +3,9 @@ error[E0277]: `()` is not a future
|
||||
|
|
||||
LL | fn get_future() -> impl Future<Output = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
|
||||
LL |
|
||||
LL | panic!()
|
||||
| -------- return type was inferred to be `_` here
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `()`
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ edition:2018
|
||||
//@compile-flags: --diagnostic-width=300
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::future::Future;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:35:21
|
||||
--> $DIR/coroutine-not-future.rs:36:21
|
||||
|
|
||||
LL | takes_coroutine(async_fn());
|
||||
| --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
|
||||
@ -7,13 +7,13 @@ LL | takes_coroutine(async_fn());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
--> $DIR/coroutine-not-future.rs:20:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:37:21
|
||||
--> $DIR/coroutine-not-future.rs:38:21
|
||||
|
|
||||
LL | takes_coroutine(returns_async_block());
|
||||
| --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
|
||||
@ -21,27 +21,27 @@ LL | takes_coroutine(returns_async_block());
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
--> $DIR/coroutine-not-future.rs:20:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:39:21
|
||||
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:40:21
|
||||
|
|
||||
LL | takes_coroutine(async {});
|
||||
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}`
|
||||
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
--> $DIR/coroutine-not-future.rs:20:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: `impl Coroutine<Yield = (), Return = ()>` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:43:18
|
||||
--> $DIR/coroutine-not-future.rs:44:18
|
||||
|
|
||||
LL | takes_future(returns_coroutine());
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine<Yield = (), Return = ()>` is not a future
|
||||
@ -50,13 +50,13 @@ LL | takes_future(returns_coroutine());
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/coroutine-not-future.rs:18:26
|
||||
--> $DIR/coroutine-not-future.rs:19:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
||||
error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:47:9
|
||||
error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:48:9
|
||||
|
|
||||
LL | takes_future(
|
||||
| ------------ required by a bound introduced by this call
|
||||
@ -65,11 +65,11 @@ LL | / |ctx| {
|
||||
LL | |
|
||||
LL | | ctx = yield ();
|
||||
LL | | },
|
||||
| |_________^ `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
|
||||
| |_________^ `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}`
|
||||
= help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}`
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/coroutine-not-future.rs:18:26
|
||||
--> $DIR/coroutine-not-future.rs:19:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
@ -20,10 +20,11 @@ error[E0277]: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as
|
||||
--> $DIR/const_param_ty_bad.rs:8:11
|
||||
|
|
||||
LL | check(|| {});
|
||||
| ----- ^^^^^ the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
|
||||
| ----- ^^^^^ unsatisfied trait bound
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
|
@ -4,7 +4,8 @@ error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
|
||||
LL | type Assoc = u16;
|
||||
| ^^^ the trait `Bar<N>` is not implemented for `u16`
|
||||
|
|
||||
= help: the trait `Bar<3>` is implemented for `u16`
|
||||
= help: the trait `Bar<N>` is not implemented for `u16`
|
||||
but trait `Bar<3>` is implemented for it
|
||||
note: required by a bound in `Foo::Assoc`
|
||||
--> $DIR/associated-type-bound-fail.rs:4:17
|
||||
|
|
||||
|
@ -18,7 +18,8 @@ LL |
|
||||
LL | 1_u32
|
||||
| ----- return type was inferred to be `u32` here
|
||||
|
|
||||
= help: the trait `Traitor<N, 2>` is implemented for `u32`
|
||||
= help: the trait `Traitor<N, N>` is not implemented for `u32`
|
||||
but trait `Traitor<N, 2>` is implemented for it
|
||||
|
||||
error[E0277]: the trait bound `u64: Traitor` is not satisfied
|
||||
--> $DIR/rp_impl_trait_fail.rs:21:13
|
||||
@ -29,7 +30,8 @@ LL |
|
||||
LL | 1_u64
|
||||
| ----- return type was inferred to be `u64` here
|
||||
|
|
||||
= help: the trait `Traitor<1, 2>` is implemented for `u64`
|
||||
= help: the trait `Traitor<1, 1>` is not implemented for `u64`
|
||||
but trait `Traitor<1, 2>` is implemented for it
|
||||
|
||||
error[E0284]: type annotations needed
|
||||
--> $DIR/rp_impl_trait_fail.rs:28:5
|
||||
|
@ -4,7 +4,8 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied
|
||||
LL | foo(&10_u32);
|
||||
| ^^^^^^^ the trait `Trait` is not implemented for `u32`
|
||||
|
|
||||
= help: the trait `Trait<2>` is implemented for `u32`
|
||||
= help: the trait `Trait<12>` is not implemented for `u32`
|
||||
but trait `Trait<2>` is implemented for it
|
||||
= note: required for the cast from `&u32` to `&dyn Trait`
|
||||
|
||||
error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
|
||||
@ -13,7 +14,8 @@ error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
|
||||
LL | bar(&true);
|
||||
| ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
|
||||
|
|
||||
= help: the trait `Traitor<2, 3>` is implemented for `bool`
|
||||
= help: the trait `Traitor<_, _>` is not implemented for `bool`
|
||||
but trait `Traitor<2, 3>` is implemented for it
|
||||
= note: required for the cast from `&bool` to `&dyn Traitor<_>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -10,7 +10,8 @@ error[E0277]: the trait bound `(): Trait<2>` is not satisfied
|
||||
LL | (): Trait<N>;
|
||||
| ^^^^^^^^ the trait `Trait<2>` is not implemented for `()`
|
||||
|
|
||||
= help: the trait `Trait<3>` is implemented for `()`
|
||||
= help: the trait `Trait<2>` is not implemented for `()`
|
||||
but trait `Trait<3>` is implemented for it
|
||||
|
||||
error[E0277]: the trait bound `(): Trait<1>` is not satisfied
|
||||
--> $DIR/wfness.rs:18:13
|
||||
@ -18,7 +19,8 @@ error[E0277]: the trait bound `(): Trait<1>` is not satisfied
|
||||
LL | fn foo() -> DependentDefaultWfness {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()`
|
||||
|
|
||||
= help: the trait `Trait<3>` is implemented for `()`
|
||||
= help: the trait `Trait<1>` is not implemented for `()`
|
||||
but trait `Trait<3>` is implemented for it
|
||||
note: required by a bound in `WhereClause`
|
||||
--> $DIR/wfness.rs:8:9
|
||||
|
|
||||
|
@ -4,7 +4,8 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
|
||||
LL | let _ = A;
|
||||
| ^ the trait `Bar<_>` is not implemented for `A<_>`
|
||||
|
|
||||
= help: the trait `Bar<_>` is implemented for `A<{ 6 + 1 }>`
|
||||
= help: the trait `Bar<_>` is not implemented for `A<_>`
|
||||
but it is implemented for `A<{ 6 + 1 }>`
|
||||
note: required by a bound in `A`
|
||||
--> $DIR/unused-substs-1.rs:9:11
|
||||
|
|
||||
|
@ -5,7 +5,10 @@ LL | fn foo() -> impl Coroutine<u8> {
|
||||
| ^^^^^^^^^^^^^^^^^^ expected due to this
|
||||
...
|
||||
LL | |_: ()| {}
|
||||
| ------- found signature defined here
|
||||
| ----------
|
||||
| |
|
||||
| found signature defined here
|
||||
| return type was inferred to be `{coroutine@$DIR/arg-count-mismatch-on-unit-input.rs:8:5: 8:12}` here
|
||||
|
|
||||
= note: expected coroutine signature `fn(u8) -> _`
|
||||
found coroutine signature `fn(()) -> _`
|
||||
|
@ -1,6 +1,7 @@
|
||||
// gate-test-coroutine_clone
|
||||
// Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held
|
||||
// across awaits can be cloned/copied.
|
||||
//@compile-flags: --diagnostic-width=300
|
||||
|
||||
#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
|
||||
|
||||
|
@ -1,76 +1,76 @@
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
--> $DIR/clone-impl.rs:49:5
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
|
||||
--> $DIR/clone-impl.rs:50:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<u32>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<u32>`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:47:14
|
||||
--> $DIR/clone-impl.rs:48:14
|
||||
|
|
||||
LL | drop(clonable_0);
|
||||
| ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
--> $DIR/clone-impl.rs:90:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
--> $DIR/clone-impl.rs:49:5
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
|
||||
--> $DIR/clone-impl.rs:50:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<char>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec<char>`
|
||||
|
|
||||
note: coroutine does not implement `Copy` as this value is used across a yield
|
||||
--> $DIR/clone-impl.rs:45:9
|
||||
--> $DIR/clone-impl.rs:46:9
|
||||
|
|
||||
LL | let v = vec!['a'];
|
||||
| - has type `Vec<char>` which does not implement `Copy`
|
||||
LL | yield;
|
||||
| ^^^^^ yield occurs here, with `v` maybe used later
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
--> $DIR/clone-impl.rs:90:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
--> $DIR/clone-impl.rs:70:5
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`
|
||||
--> $DIR/clone-impl.rs:71:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<u32>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`, the trait `Copy` is not implemented for `Vec<u32>`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:68:14
|
||||
--> $DIR/clone-impl.rs:69:14
|
||||
|
|
||||
LL | drop(clonable_1);
|
||||
| ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
--> $DIR/clone-impl.rs:90:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
--> $DIR/clone-impl.rs:70:5
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`
|
||||
--> $DIR/clone-impl.rs:71:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<char>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`, the trait `Copy` is not implemented for `Vec<char>`
|
||||
|
|
||||
note: coroutine does not implement `Copy` as this value is used across a yield
|
||||
--> $DIR/clone-impl.rs:64:9
|
||||
--> $DIR/clone-impl.rs:65:9
|
||||
|
|
||||
LL | let v = vec!['a'];
|
||||
| - has type `Vec<char>` which does not implement `Copy`
|
||||
@ -78,27 +78,27 @@ LL | let v = vec!['a'];
|
||||
LL | yield;
|
||||
| ^^^^^ yield occurs here, with `v` maybe used later
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
--> $DIR/clone-impl.rs:90:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
--> $DIR/clone-impl.rs:83:5
|
||||
error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`
|
||||
--> $DIR/clone-impl.rs:84:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`
|
||||
...
|
||||
LL | check_copy(&gen_non_clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Copy` is not implemented for `NonClone`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:81:14
|
||||
--> $DIR/clone-impl.rs:82:14
|
||||
|
|
||||
LL | drop(non_clonable);
|
||||
| ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
--> $DIR/clone-impl.rs:90:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
@ -108,22 +108,22 @@ LL + #[derive(Copy)]
|
||||
LL | struct NonClone;
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
--> $DIR/clone-impl.rs:85:5
|
||||
error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`
|
||||
--> $DIR/clone-impl.rs:86:5
|
||||
|
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`
|
||||
...
|
||||
LL | check_clone(&gen_non_clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Clone` is not implemented for `NonClone`
|
||||
|
|
||||
note: captured value does not implement `Clone`
|
||||
--> $DIR/clone-impl.rs:81:14
|
||||
--> $DIR/clone-impl.rs:82:14
|
||||
|
|
||||
LL | drop(non_clonable);
|
||||
| ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
|
||||
note: required by a bound in `check_clone`
|
||||
--> $DIR/clone-impl.rs:90:19
|
||||
--> $DIR/clone-impl.rs:91:19
|
||||
|
|
||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||
| ^^^^^ required by this bound in `check_clone`
|
||||
|
@ -3,18 +3,24 @@ error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}: C
|
||||
|
|
||||
LL | fn foo() -> impl Coroutine<Yield = u32, Return = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}`
|
||||
LL | gen { yield 42 }
|
||||
| ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}` here
|
||||
|
||||
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}: Coroutine` is not satisfied
|
||||
--> $DIR/gen_block_is_coro.rs:10:13
|
||||
|
|
||||
LL | fn bar() -> impl Coroutine<Yield = i64, Return = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}`
|
||||
LL | gen { yield 42 }
|
||||
| ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}` here
|
||||
|
||||
error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}: Coroutine` is not satisfied
|
||||
--> $DIR/gen_block_is_coro.rs:14:13
|
||||
|
|
||||
LL | fn baz() -> impl Coroutine<Yield = i32, Return = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}`
|
||||
LL | gen { yield 42 }
|
||||
| ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}` here
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -3,6 +3,8 @@ error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a fut
|
||||
|
|
||||
LL | fn foo() -> impl std::future::Future {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future
|
||||
LL | gen { yield 42 }
|
||||
| ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` here
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}`
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
//@compile-flags: --diagnostic-width=300
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutine_clone)]
|
||||
#![feature(coroutine_trait)]
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0382]: borrow of moved value: `g`
|
||||
--> $DIR/issue-105084.rs:38:14
|
||||
--> $DIR/issue-105084.rs:39:14
|
||||
|
|
||||
LL | let mut g = #[coroutine]
|
||||
| ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, which does not implement the `Copy` trait
|
||||
| ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | let mut h = copy(g);
|
||||
| - value moved here
|
||||
@ -11,7 +11,7 @@ LL | Pin::new(&mut g).resume(());
|
||||
| ^^^^^^ value borrowed here after move
|
||||
|
|
||||
note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary
|
||||
--> $DIR/issue-105084.rs:9:21
|
||||
--> $DIR/issue-105084.rs:10:21
|
||||
|
|
||||
LL | fn copy<T: Copy>(x: T) -> T {
|
||||
| ---- ^ this parameter takes ownership of the value
|
||||
@ -22,17 +22,17 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
LL | let mut h = copy(g.clone());
|
||||
| ++++++++
|
||||
|
||||
error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`
|
||||
--> $DIR/issue-105084.rs:32:17
|
||||
error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
|
||||
--> $DIR/issue-105084.rs:33:17
|
||||
|
|
||||
LL | || {
|
||||
| -- within this `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`
|
||||
| -- within this `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
|
||||
...
|
||||
LL | let mut h = copy(g);
|
||||
| ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
|
||||
| ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
|
||||
|
|
||||
note: coroutine does not implement `Copy` as this value is used across a yield
|
||||
--> $DIR/issue-105084.rs:22:22
|
||||
--> $DIR/issue-105084.rs:23:22
|
||||
|
|
||||
LL | Box::new((5, yield));
|
||||
| -------------^^^^^--
|
||||
@ -40,7 +40,7 @@ LL | Box::new((5, yield));
|
||||
| | yield occurs here, with `Box::new((5, yield))` maybe used later
|
||||
| has type `Box<(i32, ())>` which does not implement `Copy`
|
||||
note: required by a bound in `copy`
|
||||
--> $DIR/issue-105084.rs:9:12
|
||||
--> $DIR/issue-105084.rs:10:12
|
||||
|
|
||||
LL | fn copy<T: Copy>(x: T) -> T {
|
||||
| ^^^^ required by this bound in `copy`
|
||||
|
@ -14,6 +14,7 @@ fn foo(bar: bool) -> impl Coroutine<(bool,)> {
|
||||
#[coroutine]
|
||||
|bar| {
|
||||
//~^ NOTE: found signature defined here
|
||||
//~| NOTE: return type was inferred to be
|
||||
if bar {
|
||||
yield bar;
|
||||
}
|
||||
|
@ -1,11 +1,21 @@
|
||||
error[E0631]: type mismatch in coroutine arguments
|
||||
--> $DIR/issue-88653.rs:8:22
|
||||
|
|
||||
LL | fn foo(bar: bool) -> impl Coroutine<(bool,)> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
|
||||
LL | fn foo(bar: bool) -> impl Coroutine<(bool,)> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
|
||||
...
|
||||
LL | |bar| {
|
||||
| ----- found signature defined here
|
||||
LL | |bar| {
|
||||
| -----
|
||||
| |
|
||||
| _____found signature defined here
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | if bar {
|
||||
LL | | yield bar;
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____- return type was inferred to be `{coroutine@$DIR/issue-88653.rs:15:5: 15:10}` here
|
||||
|
|
||||
= note: expected coroutine signature `fn((bool,)) -> _`
|
||||
found coroutine signature `fn(bool) -> _`
|
||||
|
@ -1,15 +1,15 @@
|
||||
error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned
|
||||
--> $DIR/static-not-unpin.rs:18:18
|
||||
error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:16:5: 16:14}` cannot be unpinned
|
||||
--> $DIR/static-not-unpin.rs:19:18
|
||||
|
|
||||
LL | assert_unpin(coroutine);
|
||||
| ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}`
|
||||
| ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:16:5: 16:14}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
note: required by a bound in `assert_unpin`
|
||||
--> $DIR/static-not-unpin.rs:11:20
|
||||
--> $DIR/static-not-unpin.rs:12:20
|
||||
|
|
||||
LL | fn assert_unpin<T: Unpin>(_: T) {}
|
||||
| ^^^^^ required by this bound in `assert_unpin`
|
||||
|
@ -1,15 +1,15 @@
|
||||
error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned
|
||||
--> $DIR/static-not-unpin.rs:18:18
|
||||
error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:16:5: 16:14}` cannot be unpinned
|
||||
--> $DIR/static-not-unpin.rs:19:18
|
||||
|
|
||||
LL | assert_unpin(coroutine);
|
||||
| ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}`
|
||||
| ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:16:5: 16:14}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
note: required by a bound in `assert_unpin`
|
||||
--> $DIR/static-not-unpin.rs:11:20
|
||||
--> $DIR/static-not-unpin.rs:12:20
|
||||
|
|
||||
LL | fn assert_unpin<T: Unpin>(_: T) {}
|
||||
| ^^^^^ required by this bound in `assert_unpin`
|
||||
|
@ -1,6 +1,7 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next] compile-flags: -Znext-solver --diagnostic-width=300
|
||||
//@[current] compile-flags: --diagnostic-width=300
|
||||
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
|
@ -4,7 +4,8 @@ error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
LL | SelectInt.check("bar");
|
||||
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
|
|
||||
= help: the trait `AsExpression<Text>` is implemented for `&str`
|
||||
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
but trait `AsExpression<Text>` is implemented for it
|
||||
= help: for that trait implementation, expected `Text`, found `Integer`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -22,7 +22,8 @@ error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
LL | SelectInt.check("bar");
|
||||
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
|
|
||||
= help: the trait `AsExpression<Text>` is implemented for `&str`
|
||||
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
but trait `AsExpression<Text>` is implemented for it
|
||||
= help: for that trait implementation, expected `Text`, found `Integer`
|
||||
|
||||
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
|
||||
|
@ -16,7 +16,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
|
||||
LL | let () = K::<()>;
|
||||
| ^^ the trait `From<()>` is not implemented for `Infallible`
|
||||
|
|
||||
= help: the trait `From<!>` is implemented for `Infallible`
|
||||
= help: the trait `From<()>` is not implemented for `Infallible`
|
||||
but trait `From<!>` is implemented for it
|
||||
= help: for that trait implementation, expected `!`, found `()`
|
||||
note: required by a bound in `K`
|
||||
--> $DIR/unsatisfied-bounds.rs:12:17
|
||||
@ -48,7 +49,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
|
||||
LL | let _ = <() as Trait<&'static str>>::B::<()>;
|
||||
| ^^ the trait `From<()>` is not implemented for `Infallible`
|
||||
|
|
||||
= help: the trait `From<!>` is implemented for `Infallible`
|
||||
= help: the trait `From<()>` is not implemented for `Infallible`
|
||||
but trait `From<!>` is implemented for it
|
||||
= help: for that trait implementation, expected `!`, found `()`
|
||||
note: required by a bound in `Trait::B`
|
||||
--> $DIR/unsatisfied-bounds.rs:21:21
|
||||
|
@ -1,4 +1,4 @@
|
||||
<svg width="1104px" height="344px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="1104px" height="398px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
@ -31,31 +31,37 @@
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">the trait `Bar<i32>` is not implemented for `Struct`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="118px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> Struct</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Bar<()>` </tspan><tspan class="fg-magenta bold">is</tspan><tspan> implemented for `Struct`</tspan>
|
||||
<tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">return type was inferred to be `Struct` here</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: for that trait implementation, expected `</tspan><tspan class="fg-magenta bold">()</tspan><tspan>`, found `</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>`</tspan>
|
||||
<tspan x="10px" y="154px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="172px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required for `Struct` to implement `Foo<i32>`</tspan>
|
||||
<tspan x="10px" y="172px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Bar<</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>>` </tspan><tspan class="fg-magenta bold">is not</tspan><tspan> implemented for `Struct`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/highlight-difference-between-expected-trait-and-found-trait.rs:11:12</tspan>
|
||||
<tspan x="10px" y="190px"><tspan> but trait `Bar<</tspan><tspan class="fg-magenta bold">()</tspan><tspan>>` </tspan><tspan class="fg-magenta bold">is</tspan><tspan> implemented for it</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="208px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: for that trait implementation, expected `</tspan><tspan class="fg-magenta bold">()</tspan><tspan>`, found `</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="226px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> impl<T, K> Foo<K> for T where T: Bar<K></tspan>
|
||||
<tspan x="10px" y="226px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required for `Struct` to implement `Foo<i32>`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="244px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">unsatisfied trait bound introduced here</tspan>
|
||||
<tspan x="10px" y="244px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/highlight-difference-between-expected-trait-and-found-trait.rs:11:12</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="262px">
|
||||
<tspan x="10px" y="262px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="280px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
|
||||
<tspan x="10px" y="280px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> impl<T, K> Foo<K> for T where T: Bar<K></tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="298px">
|
||||
<tspan x="10px" y="298px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-010 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">unsatisfied trait bound introduced here</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="316px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
|
||||
<tspan x="10px" y="316px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="334px">
|
||||
<tspan x="10px" y="334px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="352px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="370px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="388px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4.4 KiB |
@ -32,7 +32,8 @@ LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||
LL | self
|
||||
| ---- return type was inferred to be `Bar` here
|
||||
|
|
||||
= help: the trait `Foo<char>` is implemented for `Bar`
|
||||
= help: the trait `Foo<u8>` is not implemented for `Bar`
|
||||
but trait `Foo<char>` is implemented for it
|
||||
= help: for that trait implementation, expected `char`, found `u8`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -12,6 +12,9 @@ error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
|
||||
|
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
|
||||
...
|
||||
LL | (S::default(), T::default())
|
||||
| ---------------------------- return type was inferred to be `(S, T)` here
|
||||
|
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
help: consider further restricting this bound
|
||||
@ -24,6 +27,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
|
||||
|
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
|
||||
...
|
||||
LL | (S::default(), T::default())
|
||||
| ---------------------------- return type was inferred to be `(S, T)` here
|
||||
|
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
help: consider further restricting this bound
|
||||
|
@ -3,6 +3,9 @@ error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}:
|
||||
|
|
||||
LL | fn foo<T>() -> Self::E {
|
||||
| ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}`
|
||||
LL |
|
||||
LL | async {}
|
||||
| -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}` here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -29,7 +29,8 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
LL | WrongImpl::foo(0i32);
|
||||
| ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
= help: the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
but trait `Raw<[_]>` is implemented for it
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:33:35
|
||||
|
|
||||
@ -67,7 +68,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||
LL | WrongImpl::<()>::foo(0i32);
|
||||
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
||||
|
|
||||
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
|
||||
= help: the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
||||
but trait `Raw<[()]>` is implemented for it
|
||||
= help: for that trait implementation, expected `[()]`, found `()`
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:33:35
|
||||
|
@ -83,7 +83,8 @@ error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied
|
||||
LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
|
||||
| ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()`
|
||||
|
|
||||
= help: the trait `Qux<'_>` is implemented for `()`
|
||||
= help: the trait `Qux<'b>` is not implemented for `&'a ()`
|
||||
but trait `Qux<'_>` is implemented for `()`
|
||||
= help: for that trait implementation, expected `()`, found `&'a ()`
|
||||
|
||||
error: implementation of `Bar` is not general enough
|
||||
@ -101,7 +102,8 @@ error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied
|
||||
LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()`
|
||||
|
|
||||
= help: the trait `Qux<'_>` is implemented for `()`
|
||||
= help: the trait `Qux<'b>` is not implemented for `&'a ()`
|
||||
but trait `Qux<'_>` is implemented for `()`
|
||||
= help: for that trait implementation, expected `()`, found `&'a ()`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user