Auto merge of #145599 - jieyouxu:rollup-523cxhm, r=jieyouxu
Rollup of 15 pull requests Successful merges: - rust-lang/rust#139345 (Extend `QueryStability` to handle `IntoIterator` implementations) - rust-lang/rust#140740 (Add `-Zindirect-branch-cs-prefix`) - rust-lang/rust#142079 (nll-relate: improve hr opaque types support) - rust-lang/rust#142938 (implement std::fs::set_permissions_nofollow on unix) - rust-lang/rust#143730 (fmt of non-decimal radix untangled) - rust-lang/rust#144767 (Correct some grammar in integer documentation) - rust-lang/rust#144906 (Require approval from t-infra instead of t-release on tier bumps) - rust-lang/rust#144983 (Rehome 37 `tests/ui/issues/` tests to other subdirectories under `tests/ui/`) - rust-lang/rust#145025 (run spellcheck as a tidy extra check in ci) - rust-lang/rust#145099 (rustc_target: Add the `32s` target feature for LoongArch) - rust-lang/rust#145166 (suggest using `pub(crate)` for E0364) - rust-lang/rust#145255 (dec2flt: Provide more valid inputs examples) - rust-lang/rust#145306 (Add tracing to various miscellaneous functions) - rust-lang/rust#145336 (Hide docs for `core::unicode`) - rust-lang/rust#145585 (Miri: fix handling of in-place argument and return place handling) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -124,8 +124,13 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||||||
// by using `ty_vid rel B` and then finally and end by equating `ty_vid` to
|
// by using `ty_vid rel B` and then finally and end by equating `ty_vid` to
|
||||||
// the opaque.
|
// the opaque.
|
||||||
let mut enable_subtyping = |ty, opaque_is_expected| {
|
let mut enable_subtyping = |ty, opaque_is_expected| {
|
||||||
let ty_vid = infcx.next_ty_var_id_in_universe(self.span(), ty::UniverseIndex::ROOT);
|
// We create the fresh inference variable in the highest universe.
|
||||||
|
// In theory we could limit it to the highest universe in the args of
|
||||||
|
// the opaque but that isn't really worth the effort.
|
||||||
|
//
|
||||||
|
// We'll make sure that the opaque type can actually name everything
|
||||||
|
// in its hidden type later on.
|
||||||
|
let ty_vid = infcx.next_ty_vid(self.span());
|
||||||
let variance = if opaque_is_expected {
|
let variance = if opaque_is_expected {
|
||||||
self.ambient_variance
|
self.ambient_variance
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -471,6 +471,15 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
|
||||||
|
llvm::add_module_flag_u32(
|
||||||
|
llmod,
|
||||||
|
llvm::ModuleFlagMergeBehavior::Override,
|
||||||
|
"indirect_branch_cs_prefix",
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
|
match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
|
||||||
{
|
{
|
||||||
// Set up the small-data optimization limit for architectures that use
|
// Set up the small-data optimization limit for architectures that use
|
||||||
|
|||||||
@@ -277,6 +277,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||||||
{
|
{
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
("loongarch32" | "loongarch64", "32s") if get_version().0 < 21 => None,
|
||||||
// Filter out features that are not supported by the current LLVM version
|
// Filter out features that are not supported by the current LLVM version
|
||||||
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
|
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ fn parse_rust_feature_flag<'a>(
|
|||||||
while let Some(new_feature) = new_features.pop() {
|
while let Some(new_feature) = new_features.pop() {
|
||||||
if features.insert(new_feature) {
|
if features.insert(new_feature) {
|
||||||
if let Some(implied_features) = inverse_implied_features.get(&new_feature) {
|
if let Some(implied_features) = inverse_implied_features.get(&new_feature) {
|
||||||
|
#[allow(rustc::potential_query_instability)]
|
||||||
new_features.extend(implied_features)
|
new_features.extend(implied_features)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ use crate::{enter_trace_span, fluent_generated as fluent};
|
|||||||
pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
|
pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
|
||||||
/// Pass a copy of the given operand.
|
/// Pass a copy of the given operand.
|
||||||
Copy(OpTy<'tcx, Prov>),
|
Copy(OpTy<'tcx, Prov>),
|
||||||
/// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
|
/// Allow for the argument to be passed in-place: destroy the value originally stored at that
|
||||||
/// make the place inaccessible for the duration of the function call.
|
/// place and make the place inaccessible for the duration of the function call. This *must* be
|
||||||
|
/// an in-memory place so that we can do the proper alias checks.
|
||||||
InPlace(MPlaceTy<'tcx, Prov>),
|
InPlace(MPlaceTy<'tcx, Prov>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,6 +380,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *Before* pushing the new frame, determine whether the return destination is in memory.
|
||||||
|
// Need to use `place_to_op` to be *sure* we get the mplace if there is one.
|
||||||
|
let destination_mplace = self.place_to_op(destination)?.as_mplace_or_imm().left();
|
||||||
|
|
||||||
|
// Push the "raw" frame -- this leaves locals uninitialized.
|
||||||
self.push_stack_frame_raw(instance, body, destination, cont)?;
|
self.push_stack_frame_raw(instance, body, destination, cont)?;
|
||||||
|
|
||||||
// If an error is raised here, pop the frame again to get an accurate backtrace.
|
// If an error is raised here, pop the frame again to get an accurate backtrace.
|
||||||
@@ -496,7 +502,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
|
|
||||||
// Protect return place for in-place return value passing.
|
// Protect return place for in-place return value passing.
|
||||||
// We only need to protect anything if this is actually an in-memory place.
|
// We only need to protect anything if this is actually an in-memory place.
|
||||||
if let Left(mplace) = destination.as_mplace_or_local() {
|
if let Some(mplace) = destination_mplace {
|
||||||
M::protect_in_place_function_argument(self, &mplace)?;
|
M::protect_in_place_function_argument(self, &mplace)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -325,8 +325,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
let _trace = enter_trace_span!(
|
let _trace = enter_trace_span!(
|
||||||
M,
|
M,
|
||||||
"instantiate_from_frame_and_normalize_erasing_regions",
|
"instantiate_from_frame_and_normalize_erasing_regions",
|
||||||
"{}",
|
%frame.instance
|
||||||
frame.instance
|
|
||||||
);
|
);
|
||||||
frame
|
frame
|
||||||
.instance
|
.instance
|
||||||
@@ -583,6 +582,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
layout: Option<TyAndLayout<'tcx>>,
|
layout: Option<TyAndLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||||
|
let _trace = enter_trace_span!(M, const_eval::eval_mir_constant, ?val);
|
||||||
let const_val = val.eval(*self.tcx, self.typing_env, span).map_err(|err| {
|
let const_val = val.eval(*self.tcx, self.typing_env, span).map_err(|err| {
|
||||||
if M::ALL_CONSTS_ARE_PRECHECKED {
|
if M::ALL_CONSTS_ARE_PRECHECKED {
|
||||||
match err {
|
match err {
|
||||||
|
|||||||
@@ -234,6 +234,12 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A place is either an mplace or some local.
|
/// A place is either an mplace or some local.
|
||||||
|
///
|
||||||
|
/// Note that the return value can be different even for logically identical places!
|
||||||
|
/// Specifically, if a local is stored in-memory, this may return `Local` or `MPlaceTy`
|
||||||
|
/// depending on how the place was constructed. In other words, seeing `Local` here does *not*
|
||||||
|
/// imply that this place does not point to memory. Every caller must therefore always handle
|
||||||
|
/// both cases.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_mplace_or_local(
|
pub fn as_mplace_or_local(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use super::{
|
|||||||
MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar, from_known_layout,
|
MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar, from_known_layout,
|
||||||
interp_ok, throw_ub, throw_unsup,
|
interp_ok, throw_ub, throw_unsup,
|
||||||
};
|
};
|
||||||
use crate::errors;
|
use crate::{enter_trace_span, errors};
|
||||||
|
|
||||||
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
|
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
|
||||||
// boundary and dropped in the other thread, it would exit the span in the other thread.
|
// boundary and dropped in the other thread, it would exit the span in the other thread.
|
||||||
@@ -386,6 +386,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
|
|
||||||
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
|
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
|
||||||
for &const_ in body.required_consts() {
|
for &const_ in body.required_consts() {
|
||||||
|
// We can't use `eval_mir_constant` here as that assumes that all required consts have
|
||||||
|
// already been checked, so we need a separate tracing call.
|
||||||
|
let _trace = enter_trace_span!(M, const_eval::required_consts, ?const_.const_);
|
||||||
let c =
|
let c =
|
||||||
self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
|
||||||
c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| {
|
c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use rustc_abi::{FIRST_VARIANT, FieldIdx};
|
use rustc_abi::{FIRST_VARIANT, FieldIdx};
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::IndexSlice;
|
use rustc_index::IndexSlice;
|
||||||
use rustc_middle::ty::{self, Instance, Ty};
|
use rustc_middle::ty::{self, Instance, Ty};
|
||||||
use rustc_middle::{bug, mir, span_bug};
|
use rustc_middle::{bug, mir, span_bug};
|
||||||
@@ -389,8 +390,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
|
|
||||||
/// Evaluate the arguments of a function call
|
/// Evaluate the arguments of a function call
|
||||||
fn eval_fn_call_argument(
|
fn eval_fn_call_argument(
|
||||||
&self,
|
&mut self,
|
||||||
op: &mir::Operand<'tcx>,
|
op: &mir::Operand<'tcx>,
|
||||||
|
move_definitely_disjoint: bool,
|
||||||
) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
|
||||||
interp_ok(match op {
|
interp_ok(match op {
|
||||||
mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
|
mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
|
||||||
@@ -399,24 +401,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
FnArg::Copy(op)
|
FnArg::Copy(op)
|
||||||
}
|
}
|
||||||
mir::Operand::Move(place) => {
|
mir::Operand::Move(place) => {
|
||||||
// If this place lives in memory, preserve its location.
|
|
||||||
// We call `place_to_op` which will be an `MPlaceTy` whenever there exists
|
|
||||||
// an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local`
|
|
||||||
// which can return a local even if that has an mplace.)
|
|
||||||
let place = self.eval_place(*place)?;
|
let place = self.eval_place(*place)?;
|
||||||
let op = self.place_to_op(&place)?;
|
if move_definitely_disjoint {
|
||||||
|
// We still have to ensure that no *other* pointers are used to access this place,
|
||||||
match op.as_mplace_or_imm() {
|
// so *if* it is in memory then we have to treat it as `InPlace`.
|
||||||
Either::Left(mplace) => FnArg::InPlace(mplace),
|
// Use `place_to_op` to guarantee that we notice it being in memory.
|
||||||
Either::Right(_imm) => {
|
let op = self.place_to_op(&place)?;
|
||||||
// This argument doesn't live in memory, so there's no place
|
match op.as_mplace_or_imm() {
|
||||||
// to make inaccessible during the call.
|
Either::Left(mplace) => FnArg::InPlace(mplace),
|
||||||
// We rely on there not being any stray `PlaceTy` that would let the
|
Either::Right(_imm) => FnArg::Copy(op),
|
||||||
// caller directly access this local!
|
|
||||||
// This is also crucial for tail calls, where we want the `FnArg` to
|
|
||||||
// stay valid when the old stack frame gets popped.
|
|
||||||
FnArg::Copy(op)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// We have to force this into memory to detect aliasing among `Move` arguments.
|
||||||
|
FnArg::InPlace(self.force_allocation(&place)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -425,18 +422,46 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
/// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
|
/// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
|
||||||
/// necessary information about callee and arguments to make a call.
|
/// necessary information about callee and arguments to make a call.
|
||||||
fn eval_callee_and_args(
|
fn eval_callee_and_args(
|
||||||
&self,
|
&mut self,
|
||||||
terminator: &mir::Terminator<'tcx>,
|
terminator: &mir::Terminator<'tcx>,
|
||||||
func: &mir::Operand<'tcx>,
|
func: &mir::Operand<'tcx>,
|
||||||
args: &[Spanned<mir::Operand<'tcx>>],
|
args: &[Spanned<mir::Operand<'tcx>>],
|
||||||
) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
|
) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
|
||||||
let func = self.eval_operand(func, None)?;
|
let func = self.eval_operand(func, None)?;
|
||||||
|
|
||||||
|
// Evaluating function call arguments. The tricky part here is dealing with `Move`
|
||||||
|
// arguments: we have to ensure no two such arguments alias. This would be most easily done
|
||||||
|
// by just forcing them all into memory and then doing the usual in-place argument
|
||||||
|
// protection, but then we'd force *a lot* of arguments into memory. So we do some syntactic
|
||||||
|
// pre-processing here where if all `move` arguments are syntactically distinct local
|
||||||
|
// variables (and none is indirect), we can skip the in-memory forcing.
|
||||||
|
let move_definitely_disjoint = 'move_definitely_disjoint: {
|
||||||
|
let mut previous_locals = FxHashSet::<mir::Local>::default();
|
||||||
|
for arg in args {
|
||||||
|
let mir::Operand::Move(place) = arg.node else {
|
||||||
|
continue; // we can skip non-`Move` arguments.
|
||||||
|
};
|
||||||
|
if place.is_indirect_first_projection() {
|
||||||
|
// An indirect `Move` argument could alias with anything else...
|
||||||
|
break 'move_definitely_disjoint false;
|
||||||
|
}
|
||||||
|
if !previous_locals.insert(place.local) {
|
||||||
|
// This local is the base for two arguments! They might overlap.
|
||||||
|
break 'move_definitely_disjoint false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We found no violation so they are all definitely disjoint.
|
||||||
|
true
|
||||||
|
};
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| self.eval_fn_call_argument(&arg.node))
|
.map(|arg| self.eval_fn_call_argument(&arg.node, move_definitely_disjoint))
|
||||||
.collect::<InterpResult<'tcx, Vec<_>>>()?;
|
.collect::<InterpResult<'tcx, Vec<_>>>()?;
|
||||||
|
|
||||||
let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
|
let fn_sig_binder = {
|
||||||
|
let _trace = enter_trace_span!(M, "fn_sig", ty = ?func.layout.ty.kind());
|
||||||
|
func.layout.ty.fn_sig(*self.tcx)
|
||||||
|
};
|
||||||
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, fn_sig_binder);
|
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, fn_sig_binder);
|
||||||
let extra_args = &args[fn_sig.inputs().len()..];
|
let extra_args = &args[fn_sig.inputs().len()..];
|
||||||
let extra_args =
|
let extra_args =
|
||||||
|
|||||||
@@ -1418,7 +1418,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
let _trace = enter_trace_span!(
|
let _trace = enter_trace_span!(
|
||||||
M,
|
M,
|
||||||
"validate_operand",
|
"validate_operand",
|
||||||
"recursive={recursive}, reset_provenance_and_padding={reset_provenance_and_padding}, val={val:?}"
|
recursive,
|
||||||
|
reset_provenance_and_padding,
|
||||||
|
?val,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
|
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use std::path::Path;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use derive_setters::Setters;
|
use derive_setters::Setters;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
|
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
|
||||||
use rustc_error_messages::{FluentArgs, SpanLabel};
|
use rustc_error_messages::{FluentArgs, SpanLabel};
|
||||||
use rustc_lexer;
|
use rustc_lexer;
|
||||||
@@ -1853,7 +1853,7 @@ impl HumanEmitter {
|
|||||||
&& line_idx + 1 == annotated_file.lines.len(),
|
&& line_idx + 1 == annotated_file.lines.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut to_add = FxHashMap::default();
|
let mut to_add = FxIndexMap::default();
|
||||||
|
|
||||||
for (depth, style) in depths {
|
for (depth, style) in depths {
|
||||||
// FIXME(#120456) - is `swap_remove` correct?
|
// FIXME(#120456) - is `swap_remove` correct?
|
||||||
|
|||||||
@@ -596,6 +596,7 @@ pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
|
|||||||
match result {
|
match result {
|
||||||
Success(body_named_matches) => {
|
Success(body_named_matches) => {
|
||||||
psess.gated_spans.merge(gated_spans_snapshot);
|
psess.gated_spans.merge(gated_spans_snapshot);
|
||||||
|
#[allow(rustc::potential_query_instability)]
|
||||||
named_matches.extend(body_named_matches);
|
named_matches.extend(body_named_matches);
|
||||||
return Ok((i, rule, named_matches));
|
return Ok((i, rule, named_matches));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -782,22 +782,30 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
self.inner.borrow_mut().type_variables().num_vars()
|
self.inner.borrow_mut().type_variables().num_vars()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_ty_vid(&self, span: Span) -> TyVid {
|
||||||
|
self.next_ty_vid_with_origin(TypeVariableOrigin { span, param_def_id: None })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_ty_vid_with_origin(&self, origin: TypeVariableOrigin) -> TyVid {
|
||||||
|
self.inner.borrow_mut().type_variables().new_var(self.universe(), origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_ty_vid_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid {
|
||||||
|
let origin = TypeVariableOrigin { span, param_def_id: None };
|
||||||
|
self.inner.borrow_mut().type_variables().new_var(universe, origin)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> {
|
pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> {
|
||||||
self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None })
|
self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||||
let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
|
let vid = self.next_ty_vid_with_origin(origin);
|
||||||
Ty::new_var(self.tcx, vid)
|
Ty::new_var(self.tcx, vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_id_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid {
|
|
||||||
let origin = TypeVariableOrigin { span, param_def_id: None };
|
|
||||||
self.inner.borrow_mut().type_variables().new_var(universe, origin)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> {
|
pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> {
|
||||||
let vid = self.next_ty_var_id_in_universe(span, universe);
|
let vid = self.next_ty_vid_in_universe(span, universe);
|
||||||
Ty::new_var(self.tcx, vid)
|
Ty::new_var(self.tcx, vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -285,7 +285,9 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
|
|||||||
.expecteds
|
.expecteds
|
||||||
.entry(name.name)
|
.entry(name.name)
|
||||||
.and_modify(|v| match v {
|
.and_modify(|v| match v {
|
||||||
ExpectedValues::Some(v) if !values_any_specified => {
|
ExpectedValues::Some(v) if !values_any_specified =>
|
||||||
|
{
|
||||||
|
#[allow(rustc::potential_query_instability)]
|
||||||
v.extend(values.clone())
|
v.extend(values.clone())
|
||||||
}
|
}
|
||||||
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
|
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
|
||||||
|
|||||||
@@ -807,6 +807,7 @@ fn test_unstable_options_tracking_hash() {
|
|||||||
tracked!(hint_mostly_unused, true);
|
tracked!(hint_mostly_unused, true);
|
||||||
tracked!(human_readable_cgu_names, true);
|
tracked!(human_readable_cgu_names, true);
|
||||||
tracked!(incremental_ignore_spans, true);
|
tracked!(incremental_ignore_spans, true);
|
||||||
|
tracked!(indirect_branch_cs_prefix, true);
|
||||||
tracked!(inline_mir, Some(true));
|
tracked!(inline_mir, Some(true));
|
||||||
tracked!(inline_mir_hint_threshold, Some(123));
|
tracked!(inline_mir_hint_threshold, Some(123));
|
||||||
tracked!(inline_mir_threshold, Some(123));
|
tracked!(inline_mir_threshold, Some(123));
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
|
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
|
||||||
//! Clippy.
|
//! Clippy.
|
||||||
|
|
||||||
use rustc_hir::HirId;
|
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
|
use rustc_hir::{Expr, ExprKind, HirId};
|
||||||
|
use rustc_middle::ty::{self, ClauseKind, GenericArgsRef, PredicatePolarity, TraitPredicate, Ty};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
use rustc_span::{Span, sym};
|
use rustc_span::{Span, sym};
|
||||||
@@ -56,25 +56,6 @@ impl LateLintPass<'_> for DefaultHashTypes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function for lints that check for expressions with calls and use typeck results to
|
|
||||||
/// get the `DefId` and `GenericArgsRef` of the function.
|
|
||||||
fn typeck_results_of_method_fn<'tcx>(
|
|
||||||
cx: &LateContext<'tcx>,
|
|
||||||
expr: &hir::Expr<'_>,
|
|
||||||
) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
|
|
||||||
match expr.kind {
|
|
||||||
hir::ExprKind::MethodCall(segment, ..)
|
|
||||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
|
|
||||||
{
|
|
||||||
Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
|
|
||||||
}
|
|
||||||
_ => match cx.typeck_results().node_type(expr.hir_id).kind() {
|
|
||||||
&ty::FnDef(def_id, args) => Some((expr.span, def_id, args)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
/// The `potential_query_instability` lint detects use of methods which can lead to
|
/// The `potential_query_instability` lint detects use of methods which can lead to
|
||||||
/// potential query instability, such as iterating over a `HashMap`.
|
/// potential query instability, such as iterating over a `HashMap`.
|
||||||
@@ -101,10 +82,12 @@ declare_tool_lint! {
|
|||||||
|
|
||||||
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
|
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
|
||||||
|
|
||||||
impl LateLintPass<'_> for QueryStability {
|
impl<'tcx> LateLintPass<'tcx> for QueryStability {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||||
let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
|
if let Some((callee_def_id, span, generic_args, _recv, _args)) =
|
||||||
if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
|
get_callee_span_generic_args_and_args(cx, expr)
|
||||||
|
&& let Ok(Some(instance)) =
|
||||||
|
ty::Instance::try_resolve(cx.tcx, cx.typing_env(), callee_def_id, generic_args)
|
||||||
{
|
{
|
||||||
let def_id = instance.def_id();
|
let def_id = instance.def_id();
|
||||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
|
||||||
@@ -113,7 +96,15 @@ impl LateLintPass<'_> for QueryStability {
|
|||||||
span,
|
span,
|
||||||
QueryInstability { query: cx.tcx.item_name(def_id) },
|
QueryInstability { query: cx.tcx.item_name(def_id) },
|
||||||
);
|
);
|
||||||
|
} else if has_unstable_into_iter_predicate(cx, callee_def_id, generic_args) {
|
||||||
|
let call_span = span.with_hi(expr.span.hi());
|
||||||
|
cx.emit_span_lint(
|
||||||
|
POTENTIAL_QUERY_INSTABILITY,
|
||||||
|
call_span,
|
||||||
|
QueryInstability { query: sym::into_iter },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) {
|
if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) {
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
UNTRACKED_QUERY_INFORMATION,
|
UNTRACKED_QUERY_INFORMATION,
|
||||||
@@ -125,6 +116,64 @@ impl LateLintPass<'_> for QueryStability {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_unstable_into_iter_predicate<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
callee_def_id: DefId,
|
||||||
|
generic_args: GenericArgsRef<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
let Some(into_iterator_def_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(into_iter_fn_def_id) = cx.tcx.lang_items().into_iter_fn() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let predicates = cx.tcx.predicates_of(callee_def_id).instantiate(cx.tcx, generic_args);
|
||||||
|
for (predicate, _) in predicates {
|
||||||
|
let ClauseKind::Trait(TraitPredicate { trait_ref, polarity: PredicatePolarity::Positive }) =
|
||||||
|
predicate.kind().skip_binder()
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
// Does the function or method require any of its arguments to implement `IntoIterator`?
|
||||||
|
if trait_ref.def_id != into_iterator_def_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let Ok(Some(instance)) =
|
||||||
|
ty::Instance::try_resolve(cx.tcx, cx.typing_env(), into_iter_fn_def_id, trait_ref.args)
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
// Does the input type's `IntoIterator` implementation have the
|
||||||
|
// `rustc_lint_query_instability` attribute on its `into_iter` method?
|
||||||
|
if cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_query_instability) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks whether an expression is a function or method call and, if so, returns its `DefId`,
|
||||||
|
/// `Span`, `GenericArgs`, and arguments. This is a slight augmentation of a similarly named Clippy
|
||||||
|
/// function, `get_callee_generic_args_and_args`.
|
||||||
|
fn get_callee_span_generic_args_and_args<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
expr: &'tcx Expr<'tcx>,
|
||||||
|
) -> Option<(DefId, Span, GenericArgsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> {
|
||||||
|
if let ExprKind::Call(callee, args) = expr.kind
|
||||||
|
&& let callee_ty = cx.typeck_results().expr_ty(callee)
|
||||||
|
&& let ty::FnDef(callee_def_id, generic_args) = callee_ty.kind()
|
||||||
|
{
|
||||||
|
return Some((*callee_def_id, callee.span, generic_args, None, args));
|
||||||
|
}
|
||||||
|
if let ExprKind::MethodCall(segment, recv, args, _) = expr.kind
|
||||||
|
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||||
|
{
|
||||||
|
let generic_args = cx.typeck_results().node_args(expr.hir_id);
|
||||||
|
return Some((method_def_id, segment.ident.span, generic_args, Some(recv), args));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
/// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
|
/// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
|
||||||
/// where `ty::<kind>` would suffice.
|
/// where `ty::<kind>` would suffice.
|
||||||
@@ -461,33 +510,22 @@ declare_tool_lint! {
|
|||||||
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
|
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
|
||||||
|
|
||||||
impl LateLintPass<'_> for Diagnostics {
|
impl LateLintPass<'_> for Diagnostics {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||||
let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
|
let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
|
||||||
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
|
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
|
||||||
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
|
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
// Only check function calls and method calls.
|
// Only check function calls and method calls.
|
||||||
let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
|
let Some((def_id, span, fn_gen_args, recv, args)) =
|
||||||
hir::ExprKind::Call(callee, args) => {
|
get_callee_span_generic_args_and_args(cx, expr)
|
||||||
match cx.typeck_results().node_type(callee.hir_id).kind() {
|
else {
|
||||||
&ty::FnDef(def_id, fn_gen_args) => {
|
return;
|
||||||
(callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
|
|
||||||
}
|
|
||||||
_ => return, // occurs for fns passed as args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir::ExprKind::MethodCall(_segment, _recv, args, _span) => {
|
|
||||||
let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let mut args = collect_args_tys_and_spans(args, true);
|
|
||||||
args.insert(0, (cx.tcx.types.self_param, _recv.span)); // dummy inserted for `self`
|
|
||||||
(span, def_id, fn_gen_args, args)
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
};
|
||||||
|
let mut arg_tys_and_spans = collect_args_tys_and_spans(args, recv.is_some());
|
||||||
|
if let Some(recv) = recv {
|
||||||
|
arg_tys_and_spans.insert(0, (cx.tcx.types.self_param, recv.span)); // dummy inserted for `self`
|
||||||
|
}
|
||||||
|
|
||||||
Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args);
|
Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args);
|
||||||
Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans);
|
Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans);
|
||||||
@@ -496,7 +534,7 @@ impl LateLintPass<'_> for Diagnostics {
|
|||||||
|
|
||||||
impl Diagnostics {
|
impl Diagnostics {
|
||||||
// Is the type `{D,Subd}iagMessage`?
|
// Is the type `{D,Subd}iagMessage`?
|
||||||
fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: MiddleTy<'cx>) -> bool {
|
fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: Ty<'cx>) -> bool {
|
||||||
if let Some(adt_def) = ty.ty_adt_def()
|
if let Some(adt_def) = ty.ty_adt_def()
|
||||||
&& let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
|
&& let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
|
||||||
&& matches!(name, sym::DiagMessage | sym::SubdiagMessage)
|
&& matches!(name, sym::DiagMessage | sym::SubdiagMessage)
|
||||||
@@ -510,7 +548,7 @@ impl Diagnostics {
|
|||||||
fn untranslatable_diagnostic<'cx>(
|
fn untranslatable_diagnostic<'cx>(
|
||||||
cx: &LateContext<'cx>,
|
cx: &LateContext<'cx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
arg_tys_and_spans: &[(MiddleTy<'cx>, Span)],
|
arg_tys_and_spans: &[(Ty<'cx>, Span)],
|
||||||
) {
|
) {
|
||||||
let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
|
let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
|
||||||
let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
|
let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ enum CanonicalizeInputKind {
|
|||||||
ParamEnv,
|
ParamEnv,
|
||||||
/// When canonicalizing predicates, we don't keep `'static`. If we're
|
/// When canonicalizing predicates, we don't keep `'static`. If we're
|
||||||
/// currently outside of the trait solver and canonicalize the root goal
|
/// currently outside of the trait solver and canonicalize the root goal
|
||||||
/// during HIR typeck, we replace each occurance of a region with a
|
/// during HIR typeck, we replace each occurrence of a region with a
|
||||||
/// unique region variable. See the comment on `InferCtxt::in_hir_typeck`
|
/// unique region variable. See the comment on `InferCtxt::in_hir_typeck`
|
||||||
/// for more details.
|
/// for more details.
|
||||||
Predicate { is_hir_typeck_root_goal: bool },
|
Predicate { is_hir_typeck_root_goal: bool },
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ resolve_consider_adding_a_derive =
|
|||||||
resolve_consider_adding_macro_export =
|
resolve_consider_adding_macro_export =
|
||||||
consider adding a `#[macro_export]` to the macro in the imported module
|
consider adding a `#[macro_export]` to the macro in the imported module
|
||||||
|
|
||||||
|
resolve_consider_marking_as_pub_crate =
|
||||||
|
in case you want to use the macro within this crate only, reduce the visibility to `pub(crate)`
|
||||||
|
|
||||||
resolve_consider_declaring_with_pub =
|
resolve_consider_declaring_with_pub =
|
||||||
consider declaring type or module `{$ident}` with `pub`
|
consider declaring type or module `{$ident}` with `pub`
|
||||||
|
|
||||||
|
|||||||
@@ -485,6 +485,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
root_span,
|
root_span,
|
||||||
root_id,
|
root_id,
|
||||||
vis,
|
vis,
|
||||||
|
vis_span: item.vis.span,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.r.indeterminate_imports.push(import);
|
self.r.indeterminate_imports.push(import);
|
||||||
@@ -977,6 +978,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
span: item.span,
|
span: item.span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis,
|
vis,
|
||||||
|
vis_span: item.vis.span,
|
||||||
});
|
});
|
||||||
if used {
|
if used {
|
||||||
self.r.import_use_map.insert(import, Used::Other);
|
self.r.import_use_map.insert(import, Used::Other);
|
||||||
@@ -1111,6 +1113,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis: Visibility::Restricted(CRATE_DEF_ID),
|
vis: Visibility::Restricted(CRATE_DEF_ID),
|
||||||
|
vis_span: item.vis.span,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1281,6 +1284,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
module_path: Vec::new(),
|
module_path: Vec::new(),
|
||||||
vis,
|
vis,
|
||||||
|
vis_span: item.vis.span,
|
||||||
});
|
});
|
||||||
self.r.import_use_map.insert(import, Used::Other);
|
self.r.import_use_map.insert(import, Used::Other);
|
||||||
let import_binding = self.r.import(binding, import);
|
let import_binding = self.r.import(binding, import);
|
||||||
|
|||||||
@@ -775,6 +775,17 @@ pub(crate) struct ConsiderAddingMacroExport {
|
|||||||
pub(crate) span: Span,
|
pub(crate) span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[suggestion(
|
||||||
|
resolve_consider_marking_as_pub_crate,
|
||||||
|
code = "pub(crate)",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
pub(crate) struct ConsiderMarkingAsPubCrate {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) vis_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[note(resolve_consider_marking_as_pub)]
|
#[note(resolve_consider_marking_as_pub)]
|
||||||
pub(crate) struct ConsiderMarkingAsPub {
|
pub(crate) struct ConsiderMarkingAsPub {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
|
|||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
||||||
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
|
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
|
||||||
ConsiderAddingMacroExport, ConsiderMarkingAsPub,
|
ConsiderAddingMacroExport, ConsiderMarkingAsPub, ConsiderMarkingAsPubCrate,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion,
|
AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion,
|
||||||
@@ -184,6 +184,9 @@ pub(crate) struct ImportData<'ra> {
|
|||||||
/// |`use foo` | `ModuleOrUniformRoot::CurrentScope` | - |
|
/// |`use foo` | `ModuleOrUniformRoot::CurrentScope` | - |
|
||||||
pub imported_module: Cell<Option<ModuleOrUniformRoot<'ra>>>,
|
pub imported_module: Cell<Option<ModuleOrUniformRoot<'ra>>>,
|
||||||
pub vis: Visibility,
|
pub vis: Visibility,
|
||||||
|
|
||||||
|
/// Span of the visibility.
|
||||||
|
pub vis_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All imports are unique and allocated on a same arena,
|
/// All imports are unique and allocated on a same arena,
|
||||||
@@ -866,7 +869,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
ImportKind::Glob { .. } => {
|
ImportKind::Glob { .. } => {
|
||||||
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
// specualtive resolution.
|
// speculative resolution.
|
||||||
self.get_mut_unchecked().resolve_glob_import(import);
|
self.get_mut_unchecked().resolve_glob_import(import);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -903,7 +906,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// We need the `target`, `source` can be extracted.
|
// We need the `target`, `source` can be extracted.
|
||||||
let imported_binding = this.import(binding, import);
|
let imported_binding = this.import(binding, import);
|
||||||
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
// specualtive resolution.
|
// speculative resolution.
|
||||||
this.get_mut_unchecked().define_binding_local(
|
this.get_mut_unchecked().define_binding_local(
|
||||||
parent,
|
parent,
|
||||||
target,
|
target,
|
||||||
@@ -917,7 +920,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
if target.name != kw::Underscore {
|
if target.name != kw::Underscore {
|
||||||
let key = BindingKey::new(target, ns);
|
let key = BindingKey::new(target, ns);
|
||||||
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
// specualtive resolution.
|
// speculative resolution.
|
||||||
this.get_mut_unchecked().update_local_resolution(
|
this.get_mut_unchecked().update_local_resolution(
|
||||||
parent,
|
parent,
|
||||||
key,
|
key,
|
||||||
@@ -1368,6 +1371,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
err.subdiagnostic( ConsiderAddingMacroExport {
|
err.subdiagnostic( ConsiderAddingMacroExport {
|
||||||
span: binding.span,
|
span: binding.span,
|
||||||
});
|
});
|
||||||
|
err.subdiagnostic( ConsiderMarkingAsPubCrate {
|
||||||
|
vis_span: import.vis_span,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
err.subdiagnostic( ConsiderMarkingAsPub {
|
err.subdiagnostic( ConsiderMarkingAsPub {
|
||||||
|
|||||||
@@ -4270,7 +4270,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
if path.len() == 2
|
if path.len() == 2
|
||||||
&& let [segment] = prefix_path
|
&& let [segment] = prefix_path
|
||||||
{
|
{
|
||||||
// Delay to check whether methond name is an associated function or not
|
// Delay to check whether method name is an associated function or not
|
||||||
// ```
|
// ```
|
||||||
// let foo = Foo {};
|
// let foo = Foo {};
|
||||||
// foo::bar(); // possibly suggest to foo.bar();
|
// foo::bar(); // possibly suggest to foo.bar();
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ session_hexadecimal_float_literal_not_supported = hexadecimal float literal is n
|
|||||||
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
|
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
|
||||||
.note = compatible flavors are: {$compatible_list}
|
.note = compatible flavors are: {$compatible_list}
|
||||||
|
|
||||||
|
session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64
|
||||||
|
|
||||||
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
|
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
|
||||||
|
|
||||||
session_int_literal_too_large = integer literal is too large
|
session_int_literal_too_large = integer literal is too large
|
||||||
|
|||||||
@@ -471,6 +471,10 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664;
|
|||||||
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
|
#[diag(session_function_return_thunk_extern_requires_non_large_code_model)]
|
||||||
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
|
pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel;
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)]
|
||||||
|
pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(session_unsupported_regparm)]
|
#[diag(session_unsupported_regparm)]
|
||||||
pub(crate) struct UnsupportedRegparm {
|
pub(crate) struct UnsupportedRegparm {
|
||||||
|
|||||||
@@ -2295,6 +2295,8 @@ options! {
|
|||||||
- hashes of green query instances
|
- hashes of green query instances
|
||||||
- hash collisions of query keys
|
- hash collisions of query keys
|
||||||
- hash collisions when creating dep-nodes"),
|
- hash collisions when creating dep-nodes"),
|
||||||
|
indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
|
||||||
|
"add `cs` prefix to `call` and `jmp` to indirect thunks (default: no)"),
|
||||||
inline_llvm: bool = (true, parse_bool, [TRACKED],
|
inline_llvm: bool = (true, parse_bool, [TRACKED],
|
||||||
"enable LLVM inlining (default: yes)"),
|
"enable LLVM inlining (default: yes)"),
|
||||||
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
|
|||||||
@@ -1368,6 +1368,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sess.opts.unstable_opts.indirect_branch_cs_prefix {
|
||||||
|
if sess.target.arch != "x86" && sess.target.arch != "x86_64" {
|
||||||
|
sess.dcx().emit_err(errors::IndirectBranchCsPrefixRequiresX86OrX8664);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(regparm) = sess.opts.unstable_opts.regparm {
|
if let Some(regparm) = sess.opts.unstable_opts.regparm {
|
||||||
if regparm > 3 {
|
if regparm > 3 {
|
||||||
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
|
sess.dcx().emit_err(errors::UnsupportedRegparm { regparm });
|
||||||
|
|||||||
@@ -767,6 +767,7 @@ static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
|||||||
|
|
||||||
static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
("32s", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("d", Stable, &["f"]),
|
("d", Stable, &["f"]),
|
||||||
("div32", Unstable(sym::loongarch_target_feature), &[]),
|
("div32", Unstable(sym::loongarch_target_feature), &[]),
|
||||||
("f", Stable, &[]),
|
("f", Stable, &[]),
|
||||||
|
|||||||
@@ -3,164 +3,78 @@
|
|||||||
use crate::fmt::NumBuffer;
|
use crate::fmt::NumBuffer;
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
use crate::num::fmt as numfmt;
|
use crate::num::fmt as numfmt;
|
||||||
use crate::ops::{Div, Rem, Sub};
|
|
||||||
use crate::{fmt, ptr, slice, str};
|
use crate::{fmt, ptr, slice, str};
|
||||||
|
|
||||||
#[doc(hidden)]
|
/// Formatting of integers with a non-decimal radix.
|
||||||
trait DisplayInt:
|
macro_rules! radix_integer {
|
||||||
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
|
(fmt::$Trait:ident for $Signed:ident and $Unsigned:ident, $prefix:literal, $dig_tab:literal) => {
|
||||||
{
|
|
||||||
fn zero() -> Self;
|
|
||||||
fn from_u8(u: u8) -> Self;
|
|
||||||
fn to_u8(&self) -> u8;
|
|
||||||
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
|
|
||||||
fn to_u32(&self) -> u32;
|
|
||||||
fn to_u64(&self) -> u64;
|
|
||||||
fn to_u128(&self) -> u128;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_int {
|
|
||||||
($($t:ident)*) => (
|
|
||||||
$(impl DisplayInt for $t {
|
|
||||||
fn zero() -> Self { 0 }
|
|
||||||
fn from_u8(u: u8) -> Self { u as Self }
|
|
||||||
fn to_u8(&self) -> u8 { *self as u8 }
|
|
||||||
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
|
|
||||||
fn to_u32(&self) -> u32 { *self as u32 }
|
|
||||||
fn to_u64(&self) -> u64 { *self as u64 }
|
|
||||||
fn to_u128(&self) -> u128 { *self as u128 }
|
|
||||||
})*
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_int! {
|
|
||||||
i8 i16 i32 i64 i128 isize
|
|
||||||
u8 u16 u32 u64 u128 usize
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that represents a specific radix
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// `digit` must return an ASCII character.
|
|
||||||
#[doc(hidden)]
|
|
||||||
unsafe trait GenericRadix: Sized {
|
|
||||||
/// The number of digits.
|
|
||||||
const BASE: u8;
|
|
||||||
|
|
||||||
/// A radix-specific prefix string.
|
|
||||||
const PREFIX: &'static str;
|
|
||||||
|
|
||||||
/// Converts an integer to corresponding radix digit.
|
|
||||||
fn digit(x: u8) -> u8;
|
|
||||||
|
|
||||||
/// Format an integer using the radix using a formatter.
|
|
||||||
fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// The radix can be as low as 2, so we need a buffer of at least 128
|
|
||||||
// characters for a base 2 number.
|
|
||||||
let zero = T::zero();
|
|
||||||
let is_nonnegative = x >= zero;
|
|
||||||
let mut buf = [MaybeUninit::<u8>::uninit(); 128];
|
|
||||||
let mut offset = buf.len();
|
|
||||||
let base = T::from_u8(Self::BASE);
|
|
||||||
if is_nonnegative {
|
|
||||||
// Accumulate each digit of the number from the least significant
|
|
||||||
// to the most significant figure.
|
|
||||||
loop {
|
|
||||||
let n = x % base; // Get the current place value.
|
|
||||||
x = x / base; // Deaccumulate the number.
|
|
||||||
offset -= 1;
|
|
||||||
buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
|
||||||
if x == zero {
|
|
||||||
// No more digits left to accumulate.
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Do the same as above, but accounting for two's complement.
|
|
||||||
loop {
|
|
||||||
let n = zero - (x % base); // Get the current place value.
|
|
||||||
x = x / base; // Deaccumulate the number.
|
|
||||||
offset -= 1;
|
|
||||||
buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
|
||||||
if x == zero {
|
|
||||||
// No more digits left to accumulate.
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
|
||||||
let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
|
|
||||||
f.pad_integral(is_nonnegative, Self::PREFIX, buf_slice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A binary (base 2) radix
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
struct Binary;
|
|
||||||
|
|
||||||
/// An octal (base 8) radix
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
struct Octal;
|
|
||||||
|
|
||||||
/// A hexadecimal (base 16) radix, formatted with lower-case characters
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
struct LowerHex;
|
|
||||||
|
|
||||||
/// A hexadecimal (base 16) radix, formatted with upper-case characters
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
struct UpperHex;
|
|
||||||
|
|
||||||
macro_rules! radix {
|
|
||||||
($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
|
|
||||||
unsafe impl GenericRadix for $T {
|
|
||||||
const BASE: u8 = $base;
|
|
||||||
const PREFIX: &'static str = $prefix;
|
|
||||||
fn digit(x: u8) -> u8 {
|
|
||||||
match x {
|
|
||||||
$($x => $conv,)+
|
|
||||||
x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x }
|
|
||||||
radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x }
|
|
||||||
radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) }
|
|
||||||
radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
|
|
||||||
|
|
||||||
macro_rules! int_base {
|
|
||||||
(fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::$Trait for $T {
|
impl fmt::$Trait for $Unsigned {
|
||||||
|
/// Format unsigned integers in the radix.
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
$Radix.fmt_int(*self as $U, f)
|
// Check macro arguments at compile time.
|
||||||
|
const {
|
||||||
|
assert!($Unsigned::MIN == 0, "need unsigned");
|
||||||
|
assert!($dig_tab.is_ascii(), "need single-byte entries");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASCII digits in ascending order are used as a lookup table.
|
||||||
|
const DIG_TAB: &[u8] = $dig_tab;
|
||||||
|
const BASE: $Unsigned = DIG_TAB.len() as $Unsigned;
|
||||||
|
const MAX_DIG_N: usize = $Unsigned::MAX.ilog(BASE) as usize + 1;
|
||||||
|
|
||||||
|
// Buffer digits of self with right alignment.
|
||||||
|
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
|
||||||
|
// Count the number of bytes in buf that are not initialized.
|
||||||
|
let mut offset = buf.len();
|
||||||
|
|
||||||
|
// Accumulate each digit of the number from the least
|
||||||
|
// significant to the most significant figure.
|
||||||
|
let mut remain = *self;
|
||||||
|
loop {
|
||||||
|
let digit = remain % BASE;
|
||||||
|
remain /= BASE;
|
||||||
|
|
||||||
|
offset -= 1;
|
||||||
|
// SAFETY: `remain` will reach 0 and we will break before `offset` wraps
|
||||||
|
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
|
||||||
|
buf[offset].write(DIG_TAB[digit as usize]);
|
||||||
|
if remain == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
||||||
|
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
|
||||||
|
f.pad_integral(true, $prefix, digits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl fmt::$Trait for $Signed {
|
||||||
|
/// Format signed integers in the two’s-complement form.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::$Trait::fmt(&self.cast_unsigned(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! integer {
|
/// Formatting of integers with a non-decimal radix.
|
||||||
($Int:ident, $Uint:ident) => {
|
macro_rules! radix_integers {
|
||||||
int_base! { fmt::Binary for $Int as $Uint -> Binary }
|
($Signed:ident, $Unsigned:ident) => {
|
||||||
int_base! { fmt::Octal for $Int as $Uint -> Octal }
|
radix_integer! { fmt::Binary for $Signed and $Unsigned, "0b", b"01" }
|
||||||
int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex }
|
radix_integer! { fmt::Octal for $Signed and $Unsigned, "0o", b"01234567" }
|
||||||
int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex }
|
radix_integer! { fmt::LowerHex for $Signed and $Unsigned, "0x", b"0123456789abcdef" }
|
||||||
|
radix_integer! { fmt::UpperHex for $Signed and $Unsigned, "0x", b"0123456789ABCDEF" }
|
||||||
int_base! { fmt::Binary for $Uint as $Uint -> Binary }
|
|
||||||
int_base! { fmt::Octal for $Uint as $Uint -> Octal }
|
|
||||||
int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
|
|
||||||
int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
integer! { isize, usize }
|
radix_integers! { isize, usize }
|
||||||
integer! { i8, u8 }
|
radix_integers! { i8, u8 }
|
||||||
integer! { i16, u16 }
|
radix_integers! { i16, u16 }
|
||||||
integer! { i32, u32 }
|
radix_integers! { i32, u32 }
|
||||||
integer! { i64, u64 }
|
radix_integers! { i64, u64 }
|
||||||
integer! { i128, u128 }
|
radix_integers! { i128, u128 }
|
||||||
|
|
||||||
macro_rules! impl_Debug {
|
macro_rules! impl_Debug {
|
||||||
($($T:ident)*) => {
|
($($T:ident)*) => {
|
||||||
@@ -205,16 +119,21 @@ unsafe fn slice_buffer_to_str(buf: &[MaybeUninit<u8>], offset: usize) -> &str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_Display {
|
macro_rules! impl_Display {
|
||||||
($($signed:ident, $unsigned:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => {
|
($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
const _: () = {
|
||||||
|
assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
|
||||||
|
assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
|
||||||
|
};
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::Display for $unsigned {
|
impl fmt::Display for $Unsigned {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "optimize_for_size"))]
|
#[cfg(not(feature = "optimize_for_size"))]
|
||||||
{
|
{
|
||||||
const MAX_DEC_N: usize = $unsigned::MAX.ilog10() as usize + 1;
|
const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
|
||||||
// Buffer decimals for $unsigned with right alignment.
|
// Buffer decimals for self with right alignment.
|
||||||
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
||||||
|
|
||||||
// SAFETY: `buf` is always big enough to contain all the digits.
|
// SAFETY: `buf` is always big enough to contain all the digits.
|
||||||
@@ -222,18 +141,20 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
{
|
{
|
||||||
$gen_name(self.$conv_fn(), true, f)
|
// Lossless conversion (with as) is asserted at the top of
|
||||||
|
// this macro.
|
||||||
|
${concat($fmt_fn, _small)}(*self as $T, true, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::Display for $signed {
|
impl fmt::Display for $Signed {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "optimize_for_size"))]
|
#[cfg(not(feature = "optimize_for_size"))]
|
||||||
{
|
{
|
||||||
const MAX_DEC_N: usize = $unsigned::MAX.ilog10() as usize + 1;
|
const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
|
||||||
// Buffer decimals for $unsigned with right alignment.
|
// Buffer decimals for self with right alignment.
|
||||||
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
||||||
|
|
||||||
// SAFETY: `buf` is always big enough to contain all the digits.
|
// SAFETY: `buf` is always big enough to contain all the digits.
|
||||||
@@ -241,13 +162,15 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
{
|
{
|
||||||
return $gen_name(self.unsigned_abs().$conv_fn(), *self >= 0, f);
|
// Lossless conversion (with as) is asserted at the top of
|
||||||
|
// this macro.
|
||||||
|
return ${concat($fmt_fn, _small)}(self.unsigned_abs() as $T, *self >= 0, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "optimize_for_size"))]
|
#[cfg(not(feature = "optimize_for_size"))]
|
||||||
impl $unsigned {
|
impl $Unsigned {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[unstable(
|
#[unstable(
|
||||||
feature = "fmt_internals",
|
feature = "fmt_internals",
|
||||||
@@ -268,7 +191,7 @@ macro_rules! impl_Display {
|
|||||||
let mut remain = self;
|
let mut remain = self;
|
||||||
|
|
||||||
// Format per four digits from the lookup table.
|
// Format per four digits from the lookup table.
|
||||||
// Four digits need a 16-bit $unsigned or wider.
|
// Four digits need a 16-bit $Unsigned or wider.
|
||||||
while size_of::<Self>() > 1 && remain > 999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)") {
|
while size_of::<Self>() > 1 && remain > 999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)") {
|
||||||
// SAFETY: All of the decimals fit in buf due to MAX_DEC_N
|
// SAFETY: All of the decimals fit in buf due to MAX_DEC_N
|
||||||
// and the while condition ensures at least 4 more decimals.
|
// and the while condition ensures at least 4 more decimals.
|
||||||
@@ -327,7 +250,7 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $signed {
|
impl $Signed {
|
||||||
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
|
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
|
||||||
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
|
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
|
||||||
///
|
///
|
||||||
@@ -337,15 +260,15 @@ macro_rules! impl_Display {
|
|||||||
/// #![feature(int_format_into)]
|
/// #![feature(int_format_into)]
|
||||||
/// use core::fmt::NumBuffer;
|
/// use core::fmt::NumBuffer;
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n = 0", stringify!($signed), ";")]
|
#[doc = concat!("let n = 0", stringify!($Signed), ";")]
|
||||||
/// let mut buf = NumBuffer::new();
|
/// let mut buf = NumBuffer::new();
|
||||||
/// assert_eq!(n.format_into(&mut buf), "0");
|
/// assert_eq!(n.format_into(&mut buf), "0");
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n1 = 32", stringify!($signed), ";")]
|
#[doc = concat!("let n1 = 32", stringify!($Signed), ";")]
|
||||||
/// assert_eq!(n1.format_into(&mut buf), "32");
|
/// assert_eq!(n1.format_into(&mut buf), "32");
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n2 = ", stringify!($signed::MAX), ";")]
|
#[doc = concat!("let n2 = ", stringify!($Signed::MAX), ";")]
|
||||||
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($signed::MAX), ".to_string());")]
|
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Signed::MAX), ".to_string());")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_format_into", issue = "138215")]
|
#[unstable(feature = "int_format_into", issue = "138215")]
|
||||||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
|
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
|
||||||
@@ -358,7 +281,9 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
{
|
{
|
||||||
offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.unsigned_abs().$conv_fn(), &mut buf.buf);
|
// Lossless conversion (with as) is asserted at the top of
|
||||||
|
// this macro.
|
||||||
|
offset = ${concat($fmt_fn, _in_buf_small)}(self.unsigned_abs() as $T, &mut buf.buf);
|
||||||
}
|
}
|
||||||
// Only difference between signed and unsigned are these 4 lines.
|
// Only difference between signed and unsigned are these 4 lines.
|
||||||
if self < 0 {
|
if self < 0 {
|
||||||
@@ -370,7 +295,7 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $unsigned {
|
impl $Unsigned {
|
||||||
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
|
/// Allows users to write an integer (in signed decimal format) into a variable `buf` of
|
||||||
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
|
/// type [`NumBuffer`] that is passed by the caller by mutable reference.
|
||||||
///
|
///
|
||||||
@@ -380,15 +305,15 @@ macro_rules! impl_Display {
|
|||||||
/// #![feature(int_format_into)]
|
/// #![feature(int_format_into)]
|
||||||
/// use core::fmt::NumBuffer;
|
/// use core::fmt::NumBuffer;
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n = 0", stringify!($unsigned), ";")]
|
#[doc = concat!("let n = 0", stringify!($Unsigned), ";")]
|
||||||
/// let mut buf = NumBuffer::new();
|
/// let mut buf = NumBuffer::new();
|
||||||
/// assert_eq!(n.format_into(&mut buf), "0");
|
/// assert_eq!(n.format_into(&mut buf), "0");
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n1 = 32", stringify!($unsigned), ";")]
|
#[doc = concat!("let n1 = 32", stringify!($Unsigned), ";")]
|
||||||
/// assert_eq!(n1.format_into(&mut buf), "32");
|
/// assert_eq!(n1.format_into(&mut buf), "32");
|
||||||
///
|
///
|
||||||
#[doc = concat!("let n2 = ", stringify!($unsigned::MAX), ";")]
|
#[doc = concat!("let n2 = ", stringify!($Unsigned::MAX), ";")]
|
||||||
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($unsigned::MAX), ".to_string());")]
|
#[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Unsigned::MAX), ".to_string());")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_format_into", issue = "138215")]
|
#[unstable(feature = "int_format_into", issue = "138215")]
|
||||||
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
|
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
|
||||||
@@ -401,7 +326,9 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
{
|
{
|
||||||
offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(self.$conv_fn(), &mut buf.buf);
|
// Lossless conversion (with as) is asserted at the top of
|
||||||
|
// this macro.
|
||||||
|
offset = ${concat($fmt_fn, _in_buf_small)}(self as $T, &mut buf.buf);
|
||||||
}
|
}
|
||||||
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
||||||
unsafe { slice_buffer_to_str(&buf.buf, offset) }
|
unsafe { slice_buffer_to_str(&buf.buf, offset) }
|
||||||
@@ -412,7 +339,7 @@ macro_rules! impl_Display {
|
|||||||
)*
|
)*
|
||||||
|
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
fn ${concat(_inner_slow_integer_to_str, $gen_name)}(mut n: $u, buf: &mut [MaybeUninit::<u8>]) -> usize {
|
fn ${concat($fmt_fn, _in_buf_small)}(mut n: $T, buf: &mut [MaybeUninit::<u8>]) -> usize {
|
||||||
let mut curr = buf.len();
|
let mut curr = buf.len();
|
||||||
|
|
||||||
// SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning
|
// SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning
|
||||||
@@ -433,11 +360,11 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "optimize_for_size")]
|
#[cfg(feature = "optimize_for_size")]
|
||||||
fn $gen_name(n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn ${concat($fmt_fn, _small)}(n: $T, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
const MAX_DEC_N: usize = $u::MAX.ilog(10) as usize + 1;
|
const MAX_DEC_N: usize = $T::MAX.ilog(10) as usize + 1;
|
||||||
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
|
||||||
|
|
||||||
let offset = ${concat(_inner_slow_integer_to_str, $gen_name)}(n, &mut buf);
|
let offset = ${concat($fmt_fn, _in_buf_small)}(n, &mut buf);
|
||||||
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
// SAFETY: Starting from `offset`, all elements of the slice have been set.
|
||||||
let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
|
let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
|
||||||
f.pad_integral(is_nonnegative, "", buf_slice)
|
f.pad_integral(is_nonnegative, "", buf_slice)
|
||||||
@@ -446,9 +373,9 @@ macro_rules! impl_Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_Exp {
|
macro_rules! impl_Exp {
|
||||||
($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
|
($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
|
||||||
fn $name(
|
fn $fmt_fn(
|
||||||
mut n: $u,
|
mut n: $T,
|
||||||
is_nonnegative: bool,
|
is_nonnegative: bool,
|
||||||
upper: bool,
|
upper: bool,
|
||||||
f: &mut fmt::Formatter<'_>
|
f: &mut fmt::Formatter<'_>
|
||||||
@@ -582,32 +509,41 @@ macro_rules! impl_Exp {
|
|||||||
|
|
||||||
$(
|
$(
|
||||||
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||||
impl fmt::LowerExp for $t {
|
impl fmt::LowerExp for $Signed {
|
||||||
#[allow(unused_comparisons)]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let is_nonnegative = *self >= 0;
|
let is_nonnegative = *self >= 0;
|
||||||
let n = if is_nonnegative {
|
let n = if is_nonnegative {
|
||||||
self.$conv_fn()
|
*self as $T
|
||||||
} else {
|
} else {
|
||||||
// convert the negative num to positive by summing 1 to its 2s complement
|
self.unsigned_abs() as $T
|
||||||
(!self.$conv_fn()).wrapping_add(1)
|
|
||||||
};
|
};
|
||||||
$name(n, is_nonnegative, false, f)
|
$fmt_fn(n, is_nonnegative, false, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||||
|
impl fmt::LowerExp for $Unsigned {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
$fmt_fn(*self as $T, true, false, f)
|
||||||
}
|
}
|
||||||
})*
|
})*
|
||||||
|
|
||||||
$(
|
$(
|
||||||
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||||
impl fmt::UpperExp for $t {
|
impl fmt::UpperExp for $Signed {
|
||||||
#[allow(unused_comparisons)]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let is_nonnegative = *self >= 0;
|
let is_nonnegative = *self >= 0;
|
||||||
let n = if is_nonnegative {
|
let n = if is_nonnegative {
|
||||||
self.$conv_fn()
|
*self as $T
|
||||||
} else {
|
} else {
|
||||||
// convert the negative num to positive by summing 1 to its 2s complement
|
self.unsigned_abs() as $T
|
||||||
(!self.$conv_fn()).wrapping_add(1)
|
|
||||||
};
|
};
|
||||||
$name(n, is_nonnegative, true, f)
|
$fmt_fn(n, is_nonnegative, true, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||||
|
impl fmt::UpperExp for $Unsigned {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
$fmt_fn(*self as $T, true, true, f)
|
||||||
}
|
}
|
||||||
})*
|
})*
|
||||||
};
|
};
|
||||||
@@ -623,37 +559,20 @@ impl_Debug! {
|
|||||||
#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
|
#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
impl_Display!(
|
impl_Display!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into display_u64);
|
||||||
i8, u8,
|
impl_Exp!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into exp_u64);
|
||||||
i16, u16,
|
|
||||||
i32, u32,
|
|
||||||
i64, u64,
|
|
||||||
isize, usize,
|
|
||||||
; as u64 via to_u64 named fmt_u64
|
|
||||||
);
|
|
||||||
impl_Exp!(
|
|
||||||
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
|
|
||||||
as u64 via to_u64 named exp_u64
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
|
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
impl_Display!(
|
impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into display_u32);
|
||||||
i8, u8,
|
impl_Display!(i64, u64; as u64 into display_u64);
|
||||||
i16, u16,
|
|
||||||
i32, u32,
|
|
||||||
isize, usize,
|
|
||||||
; as u32 via to_u32 named fmt_u32);
|
|
||||||
impl_Display!(
|
|
||||||
i64, u64,
|
|
||||||
; as u64 via to_u64 named fmt_u64);
|
|
||||||
|
|
||||||
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
|
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into exp_u32);
|
||||||
impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
|
impl_Exp!(i64, u64; as u64 into exp_u64);
|
||||||
}
|
}
|
||||||
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
|
impl_Exp!(i128, u128; as u128 into exp_u128);
|
||||||
|
|
||||||
const U128_MAX_DEC_N: usize = u128::MAX.ilog10() as usize + 1;
|
const U128_MAX_DEC_N: usize = u128::MAX.ilog10() as usize + 1;
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ macro_rules! from_str_float_impl {
|
|||||||
/// * '2.5E-10'
|
/// * '2.5E-10'
|
||||||
/// * '5.'
|
/// * '5.'
|
||||||
/// * '.5', or, equivalently, '0.5'
|
/// * '.5', or, equivalently, '0.5'
|
||||||
|
/// * '7'
|
||||||
|
/// * '007'
|
||||||
/// * 'inf', '-inf', '+infinity', 'NaN'
|
/// * 'inf', '-inf', '+infinity', 'NaN'
|
||||||
///
|
///
|
||||||
/// Note that alphabetical characters are not case-sensitive.
|
/// Note that alphabetical characters are not case-sensitive.
|
||||||
|
|||||||
@@ -2494,8 +2494,7 @@ macro_rules! int_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `i32` is used.
|
||||||
/// Which explains why `i32` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bigint_helper_methods)]
|
/// #![feature(bigint_helper_methods)]
|
||||||
@@ -2525,8 +2524,7 @@ macro_rules! int_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `i32` is used.
|
||||||
/// Which explains why `i32` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bigint_helper_methods)]
|
/// #![feature(bigint_helper_methods)]
|
||||||
@@ -2563,8 +2561,7 @@ macro_rules! int_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `i32` is used.
|
||||||
/// Which explains why `i32` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bigint_helper_methods)]
|
/// #![feature(bigint_helper_methods)]
|
||||||
|
|||||||
@@ -729,8 +729,8 @@ macro_rules! saturating_int_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `i16`
|
||||||
/// Which explains why `i16` is used here.
|
/// is used.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::num::Saturating;
|
/// use std::num::Saturating;
|
||||||
|
|||||||
@@ -2115,8 +2115,7 @@ macro_rules! uint_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `u8` is used.
|
||||||
/// Which explains why `u8` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// assert_eq!(10u8.wrapping_mul(12), 120);
|
/// assert_eq!(10u8.wrapping_mul(12), 120);
|
||||||
@@ -2606,8 +2605,8 @@ macro_rules! uint_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why why `u32`
|
||||||
/// Which explains why `u32` is used here.
|
/// is used.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// assert_eq!(5u32.overflowing_mul(2), (10, false));
|
/// assert_eq!(5u32.overflowing_mul(2), (10, false));
|
||||||
@@ -2633,8 +2632,7 @@ macro_rules! uint_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `u32` is used.
|
||||||
/// Which explains why `u32` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bigint_helper_methods)]
|
/// #![feature(bigint_helper_methods)]
|
||||||
@@ -2664,8 +2662,7 @@ macro_rules! uint_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `u32` is used.
|
||||||
/// Which explains why `u32` is used here.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(bigint_helper_methods)]
|
/// #![feature(bigint_helper_methods)]
|
||||||
|
|||||||
@@ -765,8 +765,8 @@ macro_rules! wrapping_int_impl {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Please note that this example is shared between integer types.
|
/// Please note that this example is shared among integer types, which is why `i16`
|
||||||
/// Which explains why `i16` is used here.
|
/// is used.
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
//! Unicode internals used in liballoc and libstd. Not public API.
|
||||||
#![unstable(feature = "unicode_internals", issue = "none")]
|
#![unstable(feature = "unicode_internals", issue = "none")]
|
||||||
#![allow(missing_docs)]
|
#![doc(hidden)]
|
||||||
|
|
||||||
// for use in alloc, not re-exported in std.
|
// for use in alloc, not re-exported in std.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@@ -31,5 +32,4 @@ mod unicode_data;
|
|||||||
///
|
///
|
||||||
/// The version numbering scheme is explained in
|
/// The version numbering scheme is explained in
|
||||||
/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4).
|
/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4).
|
||||||
#[stable(feature = "unicode_version", since = "1.45.0")]
|
|
||||||
pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION;
|
pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION;
|
||||||
|
|||||||
@@ -162,3 +162,183 @@ fn write_u8_min(bh: &mut Bencher) {
|
|||||||
black_box(format!("{}", black_box(u8::MIN)));
|
black_box(format!("{}", black_box(u8::MIN)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i8_bin(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(0_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(-100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(1_i8 << 4)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i16_bin(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(0_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(-100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(1_i16 << 8)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i32_bin(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(0_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(-100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(1_i32 << 16)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i64_bin(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(0_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(-100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(1_i64 << 32)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i128_bin(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(0_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(-100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:b}", black_box(1_i128 << 64)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i8_oct(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(0_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(-100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(1_i8 << 4)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i16_oct(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(0_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(-100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(1_i16 << 8)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i32_oct(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(0_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(-100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(1_i32 << 16)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i64_oct(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(0_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(-100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(1_i64 << 32)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i128_oct(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(0_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(-100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:o}", black_box(1_i128 << 64)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i8_hex(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(0_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(-100_i8)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(1_i8 << 4)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i16_hex(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(0_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(-100_i16)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(1_i16 << 8)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i32_hex(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(0_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(-100_i32)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(1_i32 << 16)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i64_hex(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(0_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(-100_i64)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(1_i64 << 32)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn write_i128_hex(bh: &mut Bencher) {
|
||||||
|
let mut buf = String::with_capacity(256);
|
||||||
|
bh.iter(|| {
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(0_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(-100_i128)).unwrap();
|
||||||
|
write!(black_box(&mut buf), "{:x}", black_box(1_i128 << 64)).unwrap();
|
||||||
|
black_box(&mut buf).clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -3156,6 +3156,25 @@ pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result
|
|||||||
fs_imp::set_permissions(path.as_ref(), perm.0)
|
fs_imp::set_permissions(path.as_ref(), perm.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the permissions of a file, unless it is a symlink.
|
||||||
|
///
|
||||||
|
/// Note that the non-final path elements are allowed to be symlinks.
|
||||||
|
///
|
||||||
|
/// # Platform-specific behavior
|
||||||
|
///
|
||||||
|
/// Currently unimplemented on Windows.
|
||||||
|
///
|
||||||
|
/// On Unix platforms, this results in a [`FilesystemLoop`] error if the last element is a symlink.
|
||||||
|
///
|
||||||
|
/// This behavior may change in the future.
|
||||||
|
///
|
||||||
|
/// [`FilesystemLoop`]: crate::io::ErrorKind::FilesystemLoop
|
||||||
|
#[doc(alias = "chmod", alias = "SetFileAttributes")]
|
||||||
|
#[unstable(feature = "set_permissions_nofollow", issue = "141607")]
|
||||||
|
pub fn set_permissions_nofollow<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
|
||||||
|
fs_imp::set_permissions_nofollow(path.as_ref(), perm)
|
||||||
|
}
|
||||||
|
|
||||||
impl DirBuilder {
|
impl DirBuilder {
|
||||||
/// Creates a new set of options with default mode/security settings for all
|
/// Creates a new set of options with default mode/security settings for all
|
||||||
/// platforms and also non-recursive.
|
/// platforms and also non-recursive.
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ pub struct MutexGuard<'a, T: ?Sized + 'a> {
|
|||||||
lock: &'a Mutex<T>,
|
lock: &'a Mutex<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`MutexGuard`] is not `Send` to maximize platform portablity.
|
/// A [`MutexGuard`] is not `Send` to maximize platform portability.
|
||||||
///
|
///
|
||||||
/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
|
/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
|
||||||
/// release mutex locks on the same thread they were acquired.
|
/// release mutex locks on the same thread they were acquired.
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ pub struct MutexGuard<'a, T: ?Sized + 'a> {
|
|||||||
poison: poison::Guard,
|
poison: poison::Guard,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`MutexGuard`] is not `Send` to maximize platform portablity.
|
/// A [`MutexGuard`] is not `Send` to maximize platform portability.
|
||||||
///
|
///
|
||||||
/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
|
/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
|
||||||
/// release mutex locks on the same thread they were acquired.
|
/// release mutex locks on the same thread they were acquired.
|
||||||
|
|||||||
@@ -114,6 +114,21 @@ pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
|||||||
with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
|
with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
|
||||||
|
use crate::fs::OpenOptions;
|
||||||
|
use crate::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
|
OpenOptions::new().custom_flags(libc::O_NOFOLLOW).open(path)?.set_permissions(perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
pub fn set_permissions_nofollow(_path: &Path, _perm: crate::fs::Permissions) -> io::Result<()> {
|
||||||
|
crate::unimplemented!(
|
||||||
|
"`set_permissions_nofollow` is currently only implemented on Unix platforms"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||||
with_native_path(path, &imp::canonicalize)
|
with_native_path(path, &imp::canonicalize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(unsafe_op_in_unsafe_fn)]
|
#![allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
/// The configure builtins provides runtime support compiler-builtin features
|
/// The configure builtins provides runtime support compiler-builtin features
|
||||||
/// which require dynamic intialization to work as expected, e.g. aarch64
|
/// which require dynamic initialization to work as expected, e.g. aarch64
|
||||||
/// outline-atomics.
|
/// outline-atomics.
|
||||||
mod configure_builtins;
|
mod configure_builtins;
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ pub(crate) mod system_time_internal {
|
|||||||
Duration::new(epoch, t.nanosecond)
|
Duration::new(epoch, t.nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This algorithm is a modifed version of the one described in the post:
|
/// This algorithm is a modified version of the one described in the post:
|
||||||
/// https://howardhinnant.github.io/date_algorithms.html#clive_from_days
|
/// https://howardhinnant.github.io/date_algorithms.html#clive_from_days
|
||||||
///
|
///
|
||||||
/// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX
|
/// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX
|
||||||
@@ -197,7 +197,7 @@ pub(crate) mod system_time_internal {
|
|||||||
// Check timzone validity
|
// Check timzone validity
|
||||||
assert!(timezone <= 1440 && timezone >= -1440);
|
assert!(timezone <= 1440 && timezone >= -1440);
|
||||||
|
|
||||||
// FIXME(#126043): use checked_sub_signed once stablized
|
// FIXME(#126043): use checked_sub_signed once stabilized
|
||||||
let secs =
|
let secs =
|
||||||
dur.as_secs().checked_add_signed((-timezone as i64) * SECS_IN_MINUTE as i64).unwrap();
|
dur.as_secs().checked_add_signed((-timezone as i64) * SECS_IN_MINUTE as i64).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ features! {
|
|||||||
/// Checks if `loongarch` feature is enabled.
|
/// Checks if `loongarch` feature is enabled.
|
||||||
/// Supported arguments are:
|
/// Supported arguments are:
|
||||||
///
|
///
|
||||||
|
/// * `"32s"`
|
||||||
/// * `"f"`
|
/// * `"f"`
|
||||||
/// * `"d"`
|
/// * `"d"`
|
||||||
/// * `"frecipe"`
|
/// * `"frecipe"`
|
||||||
@@ -22,6 +23,8 @@ features! {
|
|||||||
/// * `"lvz"`
|
/// * `"lvz"`
|
||||||
/// * `"ual"`
|
/// * `"ual"`
|
||||||
#[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")]
|
#[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")]
|
||||||
|
@FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] _32s: "32s";
|
||||||
|
/// 32S
|
||||||
@FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] f: "f";
|
@FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] f: "f";
|
||||||
/// F
|
/// F
|
||||||
@FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] d: "d";
|
@FEATURE: #[stable(feature = "stdarch_loongarch_feature", since = "1.89.0")] d: "d";
|
||||||
|
|||||||
@@ -17,22 +17,21 @@ pub(crate) fn detect_features() -> cache::Initializer {
|
|||||||
// The values are part of the platform-specific [cpucfg]
|
// The values are part of the platform-specific [cpucfg]
|
||||||
//
|
//
|
||||||
// [cpucfg]: LoongArch Reference Manual Volume 1: Basic Architecture v1.1
|
// [cpucfg]: LoongArch Reference Manual Volume 1: Basic Architecture v1.1
|
||||||
|
let cpucfg1: usize;
|
||||||
let cpucfg2: usize;
|
let cpucfg2: usize;
|
||||||
unsafe {
|
|
||||||
asm!(
|
|
||||||
"cpucfg {}, {}",
|
|
||||||
out(reg) cpucfg2, in(reg) 2,
|
|
||||||
options(pure, nomem, preserves_flags, nostack)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let cpucfg3: usize;
|
let cpucfg3: usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"cpucfg {}, {}",
|
"cpucfg {}, {}",
|
||||||
|
"cpucfg {}, {}",
|
||||||
|
"cpucfg {}, {}",
|
||||||
|
out(reg) cpucfg1, in(reg) 1,
|
||||||
|
out(reg) cpucfg2, in(reg) 2,
|
||||||
out(reg) cpucfg3, in(reg) 3,
|
out(reg) cpucfg3, in(reg) 3,
|
||||||
options(pure, nomem, preserves_flags, nostack)
|
options(pure, nomem, preserves_flags, nostack)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
enable_feature(&mut value, Feature::_32s, bit::test(cpucfg1, 0) || bit::test(cpucfg1, 1));
|
||||||
enable_feature(&mut value, Feature::frecipe, bit::test(cpucfg2, 25));
|
enable_feature(&mut value, Feature::frecipe, bit::test(cpucfg2, 25));
|
||||||
enable_feature(&mut value, Feature::div32, bit::test(cpucfg2, 26));
|
enable_feature(&mut value, Feature::div32, bit::test(cpucfg2, 26));
|
||||||
enable_feature(&mut value, Feature::lam_bh, bit::test(cpucfg2, 27));
|
enable_feature(&mut value, Feature::lam_bh, bit::test(cpucfg2, 27));
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ fn aarch64() {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
|
#[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
|
||||||
fn loongarch() {
|
fn loongarch() {
|
||||||
|
let _ = is_loongarch_feature_detected!("32s");
|
||||||
|
let _ = is_loongarch_feature_detected!("32s",);
|
||||||
let _ = is_loongarch_feature_detected!("lsx");
|
let _ = is_loongarch_feature_detected!("lsx");
|
||||||
let _ = is_loongarch_feature_detected!("lsx",);
|
let _ = is_loongarch_feature_detected!("lsx",);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,4 +45,4 @@ RUN bash -c 'npm install -g eslint@$(cat /tmp/eslint.version)'
|
|||||||
# NOTE: intentionally uses python2 for x.py so we can test it still works.
|
# NOTE: intentionally uses python2 for x.py so we can test it still works.
|
||||||
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
|
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
|
||||||
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 \
|
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 \
|
||||||
src/tools/tidy tidyselftest --extra-checks=py,cpp,js
|
src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck
|
||||||
|
|||||||
@@ -534,10 +534,10 @@ tests, and will reject patches that fail to build or pass the testsuite on a
|
|||||||
target. We hold tier 1 targets to our highest standard of requirements.
|
target. We hold tier 1 targets to our highest standard of requirements.
|
||||||
|
|
||||||
A proposed new tier 1 target must be reviewed and approved by the compiler team
|
A proposed new tier 1 target must be reviewed and approved by the compiler team
|
||||||
based on these requirements. In addition, the release team must approve the
|
based on these requirements. In addition, the infra team must approve the
|
||||||
viability and value of supporting the target. For a tier 1 target, this will
|
viability of supporting the target. For a tier 1 target, this will
|
||||||
typically take place via a full RFC proposing the target, to be jointly
|
typically take place via a full RFC proposing the target, to be jointly
|
||||||
reviewed and approved by the compiler team and release team.
|
reviewed and approved by the compiler team and infra team.
|
||||||
|
|
||||||
In addition, the infrastructure team must approve the integration of the target
|
In addition, the infrastructure team must approve the integration of the target
|
||||||
into Continuous Integration (CI), and the tier 1 CI-related requirements. This
|
into Continuous Integration (CI), and the tier 1 CI-related requirements. This
|
||||||
@@ -617,7 +617,7 @@ including the infrastructure team in the RFC proposing the target.
|
|||||||
A tier 1 target may be demoted if it no longer meets these requirements but
|
A tier 1 target may be demoted if it no longer meets these requirements but
|
||||||
still meets the requirements for a lower tier. Any proposal for demotion of a
|
still meets the requirements for a lower tier. Any proposal for demotion of a
|
||||||
tier 1 target requires a full RFC process, with approval by the compiler and
|
tier 1 target requires a full RFC process, with approval by the compiler and
|
||||||
release teams. Any such proposal will be communicated widely to the Rust
|
infra teams. Any such proposal will be communicated widely to the Rust
|
||||||
community, both when initially proposed and before being dropped from a stable
|
community, both when initially proposed and before being dropped from a stable
|
||||||
release. A tier 1 target is highly unlikely to be directly removed without
|
release. A tier 1 target is highly unlikely to be directly removed without
|
||||||
first being demoted to tier 2 or tier 3. (The amount of time between such
|
first being demoted to tier 2 or tier 3. (The amount of time between such
|
||||||
@@ -628,7 +628,7 @@ planned and scheduled action.)
|
|||||||
|
|
||||||
Raising the baseline expectations of a tier 1 target (such as the minimum CPU
|
Raising the baseline expectations of a tier 1 target (such as the minimum CPU
|
||||||
features or OS version required) requires the approval of the compiler and
|
features or OS version required) requires the approval of the compiler and
|
||||||
release teams, and should be widely communicated as well, but does not
|
infra teams, and should be widely communicated as well, but does not
|
||||||
necessarily require a full RFC.
|
necessarily require a full RFC.
|
||||||
|
|
||||||
### Tier 1 with host tools
|
### Tier 1 with host tools
|
||||||
@@ -638,11 +638,11 @@ host (such as `rustc` and `cargo`). This allows the target to be used as a
|
|||||||
development platform, not just a compilation target.
|
development platform, not just a compilation target.
|
||||||
|
|
||||||
A proposed new tier 1 target with host tools must be reviewed and approved by
|
A proposed new tier 1 target with host tools must be reviewed and approved by
|
||||||
the compiler team based on these requirements. In addition, the release team
|
the compiler team based on these requirements. In addition, the infra team
|
||||||
must approve the viability and value of supporting host tools for the target.
|
must approve the viability of supporting host tools for the target.
|
||||||
For a tier 1 target, this will typically take place via a full RFC proposing
|
For a tier 1 target, this will typically take place via a full RFC proposing
|
||||||
the target, to be jointly reviewed and approved by the compiler team and
|
the target, to be jointly reviewed and approved by the compiler team and
|
||||||
release team.
|
infra team.
|
||||||
|
|
||||||
In addition, the infrastructure team must approve the integration of the
|
In addition, the infrastructure team must approve the integration of the
|
||||||
target's host tools into Continuous Integration (CI), and the CI-related
|
target's host tools into Continuous Integration (CI), and the CI-related
|
||||||
@@ -697,7 +697,7 @@ target with host tools may be demoted (including having its host tools dropped,
|
|||||||
or being demoted to tier 2 with host tools) if it no longer meets these
|
or being demoted to tier 2 with host tools) if it no longer meets these
|
||||||
requirements but still meets the requirements for a lower tier. Any proposal
|
requirements but still meets the requirements for a lower tier. Any proposal
|
||||||
for demotion of a tier 1 target (with or without host tools) requires a full
|
for demotion of a tier 1 target (with or without host tools) requires a full
|
||||||
RFC process, with approval by the compiler and release teams. Any such proposal
|
RFC process, with approval by the compiler and infra teams. Any such proposal
|
||||||
will be communicated widely to the Rust community, both when initially proposed
|
will be communicated widely to the Rust community, both when initially proposed
|
||||||
and before being dropped from a stable release.
|
and before being dropped from a stable release.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# `indirect-branch-cs-prefix`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116852.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Option `-Zindirect-branch-cs-prefix` controls whether a `cs` prefix is added to
|
||||||
|
`call` and `jmp` to indirect thunks.
|
||||||
|
|
||||||
|
It is equivalent to [Clang]'s and [GCC]'s `-mindirect-branch-cs-prefix`. The
|
||||||
|
Linux kernel uses it for RETPOLINE builds. For details, see
|
||||||
|
[LLVM commit 6f867f910283] ("[X86] Support ``-mindirect-branch-cs-prefix`` for
|
||||||
|
call and jmp to indirect thunk") which introduces the feature.
|
||||||
|
|
||||||
|
Only x86 and x86_64 are supported.
|
||||||
|
|
||||||
|
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mindirect-branch-cs-prefix
|
||||||
|
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mindirect-branch-cs-prefix
|
||||||
|
[LLVM commit 6f867f910283]: https://github.com/llvm/llvm-project/commit/6f867f9102838ebe314c1f3661fdf95700386e5a
|
||||||
@@ -47,7 +47,7 @@ pub(crate) struct Cache {
|
|||||||
|
|
||||||
/// Similar to `paths`, but only holds external paths. This is only used for
|
/// Similar to `paths`, but only holds external paths. This is only used for
|
||||||
/// generating explicit hyperlinks to other crates.
|
/// generating explicit hyperlinks to other crates.
|
||||||
pub(crate) external_paths: FxHashMap<DefId, (Vec<Symbol>, ItemType)>,
|
pub(crate) external_paths: FxIndexMap<DefId, (Vec<Symbol>, ItemType)>,
|
||||||
|
|
||||||
/// Maps local `DefId`s of exported types to fully qualified paths.
|
/// Maps local `DefId`s of exported types to fully qualified paths.
|
||||||
/// Unlike 'paths', this mapping ignores any renames that occur
|
/// Unlike 'paths', this mapping ignores any renames that occur
|
||||||
|
|||||||
@@ -1649,7 +1649,7 @@ function preLoadCss(cssUrl) {
|
|||||||
["⏎", "Go to active search result"],
|
["⏎", "Go to active search result"],
|
||||||
["+", "Expand all sections"],
|
["+", "Expand all sections"],
|
||||||
["-", "Collapse all sections"],
|
["-", "Collapse all sections"],
|
||||||
// for the sake of brevity, we don't say "inherint impl blocks",
|
// for the sake of brevity, we don't say "inherit impl blocks",
|
||||||
// although that would be more correct,
|
// although that would be more correct,
|
||||||
// since trait impl blocks are collapsed by -
|
// since trait impl blocks are collapsed by -
|
||||||
["_", "Collapse all sections, including impl blocks"],
|
["_", "Collapse all sections, including impl blocks"],
|
||||||
|
|||||||
@@ -1111,6 +1111,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
|
|||||||
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
// For foreign items, try to see if we can emulate them.
|
// For foreign items, try to see if we can emulate them.
|
||||||
if ecx.tcx.is_foreign_item(instance.def_id()) {
|
if ecx.tcx.is_foreign_item(instance.def_id()) {
|
||||||
|
let _trace = enter_trace_span!("emulate_foreign_item");
|
||||||
// An external function call that does not have a MIR body. We either find MIR elsewhere
|
// An external function call that does not have a MIR body. We either find MIR elsewhere
|
||||||
// or emulate its effect.
|
// or emulate its effect.
|
||||||
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
|
// This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
|
||||||
@@ -1123,6 +1124,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, load the MIR.
|
// Otherwise, load the MIR.
|
||||||
|
let _trace = enter_trace_span!("load_mir");
|
||||||
interp_ok(Some((ecx.load_mir(instance.def, None)?, instance)))
|
interp_ok(Some((ecx.load_mir(instance.def, None)?, instance)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//@revisions: stack tree
|
||||||
|
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||||
|
// Validation forces more things into memory, which we can't have here.
|
||||||
|
//@compile-flags: -Zmiri-disable-validation
|
||||||
|
#![feature(custom_mir, core_intrinsics)]
|
||||||
|
use std::intrinsics::mir::*;
|
||||||
|
|
||||||
|
pub struct S(i32);
|
||||||
|
|
||||||
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
|
fn main() {
|
||||||
|
mir! {
|
||||||
|
let _unit: ();
|
||||||
|
{
|
||||||
|
let staging = S(42); // This forces `staging` into memory...
|
||||||
|
let non_copy = staging; // ... so we move it to a non-inmemory local here.
|
||||||
|
// This specifically uses a type with scalar representation to tempt Miri to use the
|
||||||
|
// efficient way of storing local variables (outside adressable memory).
|
||||||
|
Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||||
|
//~[stack]^ ERROR: not granting access
|
||||||
|
//~[tree]| ERROR: /read access .* forbidden/
|
||||||
|
}
|
||||||
|
after_call = {
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn callee(x: S, mut y: S) {
|
||||||
|
// With the setup above, if `x` and `y` are both moved,
|
||||||
|
// then writing to `y` will change the value stored in `x`!
|
||||||
|
y.0 = 0;
|
||||||
|
assert_eq!(x.0, 42);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||||
|
|
|
||||||
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
|
help: <TAG> was created here, as the root tag for ALLOC
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: <TAG> is this argument
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | y.0 = 0;
|
||||||
|
| ^^^^^^^
|
||||||
|
= note: BACKTRACE (of the first span):
|
||||||
|
= note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
error: Undefined Behavior: read access through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||||
|
|
|
||||||
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
||||||
|
= help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
|
||||||
|
= help: this foreign read access would cause the protected tag <TAG> (currently Active) to become Disabled
|
||||||
|
= help: protected tags must never be Disabled
|
||||||
|
help: the accessed tag <TAG> was created here
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: the protected tag <TAG> was created here, in the initial state Reserved
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | y.0 = 0;
|
||||||
|
| ^^^^^^^
|
||||||
|
help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4]
|
||||||
|
--> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | y.0 = 0;
|
||||||
|
| ^^^^^^^
|
||||||
|
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
|
||||||
|
= note: BACKTRACE (of the first span):
|
||||||
|
= note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
@@ -11,8 +11,8 @@ LL | unsafe { ptr.read() };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
|
Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation:
|
||||||
ALLOC (stack variable, size: 4, align: 4) {
|
ALLOC (stack variable, size: 4, align: 4) {
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ use std::intrinsics::mir::*;
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
mir! {
|
mir! {
|
||||||
{
|
{
|
||||||
let x = 0;
|
let _x = 0;
|
||||||
let ptr = &raw mut x;
|
let ptr = &raw mut _x;
|
||||||
// We arrange for `myfun` to have a pointer that aliases
|
// We arrange for `myfun` to have a pointer that aliases
|
||||||
// its return place. Even just reading from that pointer is UB.
|
// its return place. Even just reading from that pointer is UB.
|
||||||
Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
}
|
}
|
||||||
|
|
||||||
after_call = {
|
after_call = {
|
||||||
@@ -25,7 +25,7 @@ pub fn main() {
|
|||||||
|
|
||||||
fn myfun(ptr: *mut i32) -> i32 {
|
fn myfun(ptr: *mut i32) -> i32 {
|
||||||
unsafe { ptr.read() };
|
unsafe { ptr.read() };
|
||||||
//~[stack]^ ERROR: not granting access
|
//~[stack]^ ERROR: does not exist in the borrow stack
|
||||||
//~[tree]| ERROR: /read access .* forbidden/
|
//~[tree]| ERROR: /read access .* forbidden/
|
||||||
//~[none]| ERROR: uninitialized
|
//~[none]| ERROR: uninitialized
|
||||||
// Without an aliasing model, reads are "fine" but at least they return uninit data.
|
// Without an aliasing model, reads are "fine" but at least they return uninit data.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
|
error: Undefined Behavior: attempting a read access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.read() };
|
LL | unsafe { ptr.read() };
|
||||||
| ^^^^^^^^^^ Undefined Behavior occurred here
|
| ^^^^^^^^^^ this error occurs as part of an access at ALLOC[0x0..0x4]
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
@@ -11,12 +11,12 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
|
|||||||
|
|
|
|
||||||
LL | / mir! {
|
LL | / mir! {
|
||||||
LL | | {
|
LL | | {
|
||||||
LL | | let x = 0;
|
LL | | let _x = 0;
|
||||||
LL | | let ptr = &raw mut x;
|
LL | | let ptr = &raw mut _x;
|
||||||
... |
|
... |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
help: <TAG> is this argument
|
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.read() };
|
LL | unsafe { ptr.read() };
|
||||||
@@ -26,8 +26,8 @@ LL | unsafe { ptr.read() };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ help: the accessed tag <TAG> was created here
|
|||||||
|
|
|
|
||||||
LL | / mir! {
|
LL | / mir! {
|
||||||
LL | | {
|
LL | | {
|
||||||
LL | | let x = 0;
|
LL | | let _x = 0;
|
||||||
LL | | let ptr = &raw mut x;
|
LL | | let ptr = &raw mut _x;
|
||||||
... |
|
... |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
@@ -34,8 +34,8 @@ LL | unsafe { ptr.read() };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub fn main() {
|
|||||||
let ptr = &raw mut _x;
|
let ptr = &raw mut _x;
|
||||||
// We arrange for `myfun` to have a pointer that aliases
|
// We arrange for `myfun` to have a pointer that aliases
|
||||||
// its return place. Writing to that pointer is UB.
|
// its return place. Writing to that pointer is UB.
|
||||||
Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
}
|
}
|
||||||
|
|
||||||
after_call = {
|
after_call = {
|
||||||
@@ -26,7 +26,7 @@ pub fn main() {
|
|||||||
fn myfun(ptr: *mut i32) -> i32 {
|
fn myfun(ptr: *mut i32) -> i32 {
|
||||||
// This overwrites the return place, which shouldn't be possible through another pointer.
|
// This overwrites the return place, which shouldn't be possible through another pointer.
|
||||||
unsafe { ptr.write(0) };
|
unsafe { ptr.write(0) };
|
||||||
//~[stack]^ ERROR: strongly protected
|
//~[stack]^ ERROR: does not exist in the borrow stack
|
||||||
//~[tree]| ERROR: /write access .* forbidden/
|
//~[tree]| ERROR: /write access .* forbidden/
|
||||||
13
|
13
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
|
error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.write(0) };
|
LL | unsafe { ptr.write(0) };
|
||||||
| ^^^^^^^^^^^^ Undefined Behavior occurred here
|
| ^^^^^^^^^^^^ this error occurs as part of an access at ALLOC[0x0..0x4]
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
@@ -16,7 +16,7 @@ LL | | let ptr = &raw mut _x;
|
|||||||
... |
|
... |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
help: <TAG> is this argument
|
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.write(0) };
|
LL | unsafe { ptr.write(0) };
|
||||||
@@ -26,8 +26,8 @@ LL | unsafe { ptr.write(0) };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ LL | unsafe { ptr.write(0) };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub fn main() {
|
|||||||
let ptr = &raw mut _x;
|
let ptr = &raw mut _x;
|
||||||
// We arrange for `myfun` to have a pointer that aliases
|
// We arrange for `myfun` to have a pointer that aliases
|
||||||
// its return place. Writing to that pointer is UB.
|
// its return place. Writing to that pointer is UB.
|
||||||
Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
}
|
}
|
||||||
|
|
||||||
after_call = {
|
after_call = {
|
||||||
@@ -32,7 +32,7 @@ fn myfun(ptr: *mut i32) -> i32 {
|
|||||||
fn myfun2(ptr: *mut i32) -> i32 {
|
fn myfun2(ptr: *mut i32) -> i32 {
|
||||||
// This overwrites the return place, which shouldn't be possible through another pointer.
|
// This overwrites the return place, which shouldn't be possible through another pointer.
|
||||||
unsafe { ptr.write(0) };
|
unsafe { ptr.write(0) };
|
||||||
//~[stack]^ ERROR: strongly protected
|
//~[stack]^ ERROR: does not exist in the borrow stack
|
||||||
//~[tree]| ERROR: /write access .* forbidden/
|
//~[tree]| ERROR: /write access .* forbidden/
|
||||||
13
|
13
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
|
error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.write(0) };
|
LL | unsafe { ptr.write(0) };
|
||||||
| ^^^^^^^^^^^^ Undefined Behavior occurred here
|
| ^^^^^^^^^^^^ this error occurs as part of an access at ALLOC[0x0..0x4]
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
@@ -16,18 +16,18 @@ LL | | let ptr = &raw mut _x;
|
|||||||
... |
|
... |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
help: <TAG> is this argument
|
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { ptr.write(0) };
|
LL | become myfun2(ptr)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
= note: BACKTRACE (of the first span):
|
= note: BACKTRACE (of the first span):
|
||||||
= note: inside `myfun2` at tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
= note: inside `myfun2` at tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ LL | unsafe { ptr.write(0) };
|
|||||||
note: inside `main`
|
note: inside `main`
|
||||||
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
--> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ const RUFF_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "ruff.toml
|
|||||||
const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"];
|
const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"];
|
||||||
const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"];
|
const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"];
|
||||||
|
|
||||||
// this must be kept in sync with with .github/workflows/spellcheck.yml
|
|
||||||
const SPELLCHECK_DIRS: &[&str] = &["compiler", "library", "src/bootstrap", "src/librustdoc"];
|
const SPELLCHECK_DIRS: &[&str] = &["compiler", "library", "src/bootstrap", "src/librustdoc"];
|
||||||
|
|
||||||
pub fn check(
|
pub fn check(
|
||||||
@@ -51,6 +50,7 @@ pub fn check(
|
|||||||
librustdoc_path: &Path,
|
librustdoc_path: &Path,
|
||||||
tools_path: &Path,
|
tools_path: &Path,
|
||||||
npm: &Path,
|
npm: &Path,
|
||||||
|
cargo: &Path,
|
||||||
bless: bool,
|
bless: bool,
|
||||||
extra_checks: Option<&str>,
|
extra_checks: Option<&str>,
|
||||||
pos_args: &[String],
|
pos_args: &[String],
|
||||||
@@ -63,6 +63,7 @@ pub fn check(
|
|||||||
librustdoc_path,
|
librustdoc_path,
|
||||||
tools_path,
|
tools_path,
|
||||||
npm,
|
npm,
|
||||||
|
cargo,
|
||||||
bless,
|
bless,
|
||||||
extra_checks,
|
extra_checks,
|
||||||
pos_args,
|
pos_args,
|
||||||
@@ -78,6 +79,7 @@ fn check_impl(
|
|||||||
librustdoc_path: &Path,
|
librustdoc_path: &Path,
|
||||||
tools_path: &Path,
|
tools_path: &Path,
|
||||||
npm: &Path,
|
npm: &Path,
|
||||||
|
cargo: &Path,
|
||||||
bless: bool,
|
bless: bool,
|
||||||
extra_checks: Option<&str>,
|
extra_checks: Option<&str>,
|
||||||
pos_args: &[String],
|
pos_args: &[String],
|
||||||
@@ -293,7 +295,7 @@ fn check_impl(
|
|||||||
} else {
|
} else {
|
||||||
eprintln!("spellcheck files");
|
eprintln!("spellcheck files");
|
||||||
}
|
}
|
||||||
spellcheck_runner(&args)?;
|
spellcheck_runner(root_path, &outdir, &cargo, &args)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if js_lint || js_typecheck {
|
if js_lint || js_typecheck {
|
||||||
@@ -576,34 +578,25 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> {
|
|||||||
if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) }
|
if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that spellchecker is installed then run it at the given path
|
/// Ensure that spellchecker is installed then run it at the given path
|
||||||
fn spellcheck_runner(args: &[&str]) -> Result<(), Error> {
|
fn spellcheck_runner(
|
||||||
// sync version with .github/workflows/spellcheck.yml
|
src_root: &Path,
|
||||||
let expected_version = "typos-cli 1.34.0";
|
outdir: &Path,
|
||||||
match Command::new("typos").arg("--version").output() {
|
cargo: &Path,
|
||||||
Ok(o) => {
|
args: &[&str],
|
||||||
let stdout = String::from_utf8_lossy(&o.stdout);
|
) -> Result<(), Error> {
|
||||||
if stdout.trim() != expected_version {
|
let bin_path =
|
||||||
return Err(Error::Version {
|
crate::ensure_version_or_cargo_install(outdir, cargo, "typos-cli", "typos", "1.34.0")?;
|
||||||
program: "typos",
|
match Command::new(bin_path).current_dir(src_root).args(args).status() {
|
||||||
required: expected_version,
|
Ok(status) => {
|
||||||
installed: stdout.trim().to_string(),
|
if status.success() {
|
||||||
});
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::FailedCheck("typos"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == io::ErrorKind::NotFound => {
|
Err(err) => Err(Error::Generic(format!("failed to run typos tool: {err:?}"))),
|
||||||
return Err(Error::MissingReq(
|
|
||||||
"typos",
|
|
||||||
"spellcheck file checks",
|
|
||||||
// sync version with .github/workflows/spellcheck.yml
|
|
||||||
Some("install tool via `cargo install typos-cli@1.34.0`".to_owned()),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Err(e) => return Err(e.into()),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = Command::new("typos").args(args).status()?;
|
|
||||||
if status.success() { Ok(()) } else { Err(Error::FailedCheck("typos")) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check git for tracked files matching an extension
|
/// Check git for tracked files matching an extension
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
//! to be used by tools.
|
//! to be used by tools.
|
||||||
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::{env, io};
|
||||||
|
|
||||||
use build_helper::ci::CiEnv;
|
use build_helper::ci::CiEnv;
|
||||||
use build_helper::git::{GitConfig, get_closest_upstream_commit};
|
use build_helper::git::{GitConfig, get_closest_upstream_commit};
|
||||||
@@ -180,6 +182,70 @@ pub fn files_modified(ci_info: &CiInfo, pred: impl Fn(&str) -> bool) -> bool {
|
|||||||
!v.is_empty()
|
!v.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the given executable is installed with the given version, use that,
|
||||||
|
/// otherwise install via cargo.
|
||||||
|
pub fn ensure_version_or_cargo_install(
|
||||||
|
build_dir: &Path,
|
||||||
|
cargo: &Path,
|
||||||
|
pkg_name: &str,
|
||||||
|
bin_name: &str,
|
||||||
|
version: &str,
|
||||||
|
) -> io::Result<PathBuf> {
|
||||||
|
// ignore the process exit code here and instead just let the version number check fail.
|
||||||
|
// we also importantly don't return if the program wasn't installed,
|
||||||
|
// instead we want to continue to the fallback.
|
||||||
|
'ck: {
|
||||||
|
// FIXME: rewrite as if-let chain once this crate is 2024 edition.
|
||||||
|
let Ok(output) = Command::new(bin_name).arg("--version").output() else {
|
||||||
|
break 'ck;
|
||||||
|
};
|
||||||
|
let Ok(s) = str::from_utf8(&output.stdout) else {
|
||||||
|
break 'ck;
|
||||||
|
};
|
||||||
|
let Some(v) = s.trim().split_whitespace().last() else {
|
||||||
|
break 'ck;
|
||||||
|
};
|
||||||
|
if v == version {
|
||||||
|
return Ok(PathBuf::from(bin_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tool_root_dir = build_dir.join("misc-tools");
|
||||||
|
let tool_bin_dir = tool_root_dir.join("bin");
|
||||||
|
eprintln!("building external tool {bin_name} from package {pkg_name}@{version}");
|
||||||
|
// use --force to ensure that if the required version is bumped, we update it.
|
||||||
|
// use --target-dir to ensure we have a build cache so repeated invocations aren't slow.
|
||||||
|
// modify PATH so that cargo doesn't print a warning telling the user to modify the path.
|
||||||
|
let cargo_exit_code = Command::new(cargo)
|
||||||
|
.args(["install", "--locked", "--force", "--quiet"])
|
||||||
|
.arg("--root")
|
||||||
|
.arg(&tool_root_dir)
|
||||||
|
.arg("--target-dir")
|
||||||
|
.arg(tool_root_dir.join("target"))
|
||||||
|
.arg(format!("{pkg_name}@{version}"))
|
||||||
|
.env(
|
||||||
|
"PATH",
|
||||||
|
env::join_paths(
|
||||||
|
env::split_paths(&env::var("PATH").unwrap())
|
||||||
|
.chain(std::iter::once(tool_bin_dir.clone())),
|
||||||
|
)
|
||||||
|
.expect("build dir contains invalid char"),
|
||||||
|
)
|
||||||
|
.env("RUSTFLAGS", "-Copt-level=0")
|
||||||
|
.spawn()?
|
||||||
|
.wait()?;
|
||||||
|
if !cargo_exit_code.success() {
|
||||||
|
return Err(io::Error::other("cargo install failed"));
|
||||||
|
}
|
||||||
|
let bin_path = tool_bin_dir.join(bin_name);
|
||||||
|
assert!(
|
||||||
|
matches!(bin_path.try_exists(), Ok(true)),
|
||||||
|
"cargo install did not produce the expected binary"
|
||||||
|
);
|
||||||
|
eprintln!("finished building tool {bin_name}");
|
||||||
|
Ok(bin_path)
|
||||||
|
}
|
||||||
|
|
||||||
pub mod alphabetical;
|
pub mod alphabetical;
|
||||||
pub mod bins;
|
pub mod bins;
|
||||||
pub mod debug_artifacts;
|
pub mod debug_artifacts;
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ fn main() {
|
|||||||
&librustdoc_path,
|
&librustdoc_path,
|
||||||
&tools_path,
|
&tools_path,
|
||||||
&npm,
|
&npm,
|
||||||
|
&cargo,
|
||||||
bless,
|
bless,
|
||||||
extra_checks,
|
extra_checks,
|
||||||
pos_args
|
pos_args
|
||||||
|
|||||||
27
tests/assembly-llvm/x86_64-indirect-branch-cs-prefix.rs
Normal file
27
tests/assembly-llvm/x86_64-indirect-branch-cs-prefix.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Test that the `cs` prefix is (not) added into a `call` and a `jmp` to the
|
||||||
|
// indirect thunk when the `-Zindirect-branch-cs-prefix` flag is (not) set.
|
||||||
|
|
||||||
|
//@ revisions: unset set
|
||||||
|
//@ assembly-output: emit-asm
|
||||||
|
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=retpoline,retpoline-external-thunk,indirect-branch-cs-prefix -Zretpoline-external-thunk
|
||||||
|
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
|
||||||
|
//@ only-x86_64
|
||||||
|
//@ ignore-apple Symbol is called `___x86_indirect_thunk` (Darwin's extra underscore)
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// CHECK-LABEL: foo:
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn foo(g: fn()) {
|
||||||
|
// unset-NOT: cs
|
||||||
|
// unset: callq {{__x86_indirect_thunk.*}}
|
||||||
|
// set: cs
|
||||||
|
// set-NEXT: callq {{__x86_indirect_thunk.*}}
|
||||||
|
g();
|
||||||
|
|
||||||
|
// unset-NOT: cs
|
||||||
|
// unset: jmp {{__x86_indirect_thunk.*}}
|
||||||
|
// set: cs
|
||||||
|
// set-NEXT: jmp {{__x86_indirect_thunk.*}}
|
||||||
|
g();
|
||||||
|
}
|
||||||
18
tests/codegen-llvm/indirect-branch-cs-prefix.rs
Normal file
18
tests/codegen-llvm/indirect-branch-cs-prefix.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Test that the `indirect_branch_cs_prefix` module attribute is (not)
|
||||||
|
// emitted when the `-Zindirect-branch-cs-prefix` flag is (not) set.
|
||||||
|
|
||||||
|
//@ add-core-stubs
|
||||||
|
//@ revisions: unset set
|
||||||
|
//@ needs-llvm-components: x86
|
||||||
|
//@ compile-flags: --target x86_64-unknown-linux-gnu
|
||||||
|
//@ [set] compile-flags: -Zindirect-branch-cs-prefix
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(no_core, lang_items)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
extern crate minicore;
|
||||||
|
use minicore::*;
|
||||||
|
|
||||||
|
// unset-NOT: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
|
||||||
|
// set: !{{[0-9]+}} = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
//@ compile-flags: -Z unstable-options
|
//@ compile-flags: -Z unstable-options
|
||||||
|
//@ ignore-stage1
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![deny(rustc::potential_query_instability)]
|
#![deny(rustc::potential_query_instability)]
|
||||||
@@ -34,4 +35,16 @@ fn main() {
|
|||||||
//~^ ERROR using `values_mut` can result in unstable query results
|
//~^ ERROR using `values_mut` can result in unstable query results
|
||||||
*val = *val + 10;
|
*val = *val + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FxHashMap::<u32, i32>::default().extend(x);
|
||||||
|
//~^ ERROR using `into_iter` can result in unstable query results
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hide_into_iter<T>(x: impl IntoIterator<Item = T>) -> impl Iterator<Item = T> {
|
||||||
|
x.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take(map: std::collections::HashMap<i32, i32>) {
|
||||||
|
_ = hide_into_iter(map);
|
||||||
|
//~^ ERROR using `into_iter` can result in unstable query results
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
error: using `drain` can result in unstable query results
|
error: using `drain` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:13:16
|
--> $DIR/query_stability.rs:14:16
|
||||||
|
|
|
|
||||||
LL | for _ in x.drain() {}
|
LL | for _ in x.drain() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/query_stability.rs:4:9
|
--> $DIR/query_stability.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![deny(rustc::potential_query_instability)]
|
LL | #![deny(rustc::potential_query_instability)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: using `iter` can result in unstable query results
|
error: using `iter` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:16:16
|
--> $DIR/query_stability.rs:17:16
|
||||||
|
|
|
|
||||||
LL | for _ in x.iter() {}
|
LL | for _ in x.iter() {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
@@ -20,7 +20,7 @@ LL | for _ in x.iter() {}
|
|||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: using `iter_mut` can result in unstable query results
|
error: using `iter_mut` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:19:36
|
--> $DIR/query_stability.rs:20:36
|
||||||
|
|
|
|
||||||
LL | for _ in Some(&mut x).unwrap().iter_mut() {}
|
LL | for _ in Some(&mut x).unwrap().iter_mut() {}
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@@ -28,7 +28,7 @@ LL | for _ in Some(&mut x).unwrap().iter_mut() {}
|
|||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: using `into_iter` can result in unstable query results
|
error: using `into_iter` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:22:14
|
--> $DIR/query_stability.rs:23:14
|
||||||
|
|
|
|
||||||
LL | for _ in x {}
|
LL | for _ in x {}
|
||||||
| ^
|
| ^
|
||||||
@@ -36,7 +36,7 @@ LL | for _ in x {}
|
|||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: using `keys` can result in unstable query results
|
error: using `keys` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:26:15
|
--> $DIR/query_stability.rs:27:15
|
||||||
|
|
|
|
||||||
LL | let _ = x.keys();
|
LL | let _ = x.keys();
|
||||||
| ^^^^
|
| ^^^^
|
||||||
@@ -44,7 +44,7 @@ LL | let _ = x.keys();
|
|||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: using `values` can result in unstable query results
|
error: using `values` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:29:15
|
--> $DIR/query_stability.rs:30:15
|
||||||
|
|
|
|
||||||
LL | let _ = x.values();
|
LL | let _ = x.values();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
@@ -52,12 +52,28 @@ LL | let _ = x.values();
|
|||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: using `values_mut` can result in unstable query results
|
error: using `values_mut` can result in unstable query results
|
||||||
--> $DIR/query_stability.rs:33:18
|
--> $DIR/query_stability.rs:34:18
|
||||||
|
|
|
|
||||||
LL | for val in x.values_mut() {
|
LL | for val in x.values_mut() {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: using `into_iter` can result in unstable query results
|
||||||
|
--> $DIR/query_stability.rs:39:38
|
||||||
|
|
|
||||||
|
LL | FxHashMap::<u32, i32>::default().extend(x);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
|
error: using `into_iter` can result in unstable query results
|
||||||
|
--> $DIR/query_stability.rs:48:9
|
||||||
|
|
|
||||||
|
LL | _ = hide_into_iter(map);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8498
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/7784
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/78622
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0223]: ambiguous associated type
|
error[E0223]: ambiguous associated type
|
||||||
--> $DIR/issue-78622.rs:5:5
|
--> $DIR/ambiguous-associated-type-error-78622.rs:6:5
|
||||||
|
|
|
|
||||||
LL | S::A::<f> {}
|
LL | S::A::<f> {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/78957
|
||||||
#![deny(unused_attributes)]
|
#![deny(unused_attributes)]
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
error: `#[inline]` attribute cannot be used on function params
|
error: `#[inline]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:5:16
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:6:16
|
||||||
|
|
|
|
||||||
LL | pub struct Foo<#[inline] const N: usize>;
|
LL | pub struct Foo<#[inline] const N: usize>;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@@ -7,7 +7,7 @@ LL | pub struct Foo<#[inline] const N: usize>;
|
|||||||
= help: `#[inline]` can only be applied to functions
|
= help: `#[inline]` can only be applied to functions
|
||||||
|
|
||||||
error: `#[inline]` attribute cannot be used on function params
|
error: `#[inline]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:13:17
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:14:17
|
||||||
|
|
|
|
||||||
LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
|
LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@@ -15,7 +15,7 @@ LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
|
|||||||
= help: `#[inline]` can only be applied to functions
|
= help: `#[inline]` can only be applied to functions
|
||||||
|
|
||||||
error: `#[inline]` attribute cannot be used on function params
|
error: `#[inline]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:21:17
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:22:17
|
||||||
|
|
|
|
||||||
LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
|
LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@@ -23,25 +23,25 @@ LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
|
|||||||
= help: `#[inline]` can only be applied to functions
|
= help: `#[inline]` can only be applied to functions
|
||||||
|
|
||||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||||
--> $DIR/issue-78957.rs:10:23
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:11:23
|
||||||
|
|
|
|
||||||
LL | pub struct Baz<#[repr(C)] const N: usize>;
|
LL | pub struct Baz<#[repr(C)] const N: usize>;
|
||||||
| ^ -------------- not a struct, enum, or union
|
| ^ -------------- not a struct, enum, or union
|
||||||
|
|
||||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||||
--> $DIR/issue-78957.rs:18:24
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:19:24
|
||||||
|
|
|
|
||||||
LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
|
LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
|
||||||
| ^ -- not a struct, enum, or union
|
| ^ -- not a struct, enum, or union
|
||||||
|
|
||||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||||
--> $DIR/issue-78957.rs:26:24
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:27:24
|
||||||
|
|
|
|
||||||
LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
|
LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
|
||||||
| ^ - not a struct, enum, or union
|
| ^ - not a struct, enum, or union
|
||||||
|
|
||||||
error: `#[cold]` attribute cannot be used on function params
|
error: `#[cold]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:7:16
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:8:16
|
||||||
|
|
|
|
||||||
LL | pub struct Bar<#[cold] const N: usize>;
|
LL | pub struct Bar<#[cold] const N: usize>;
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -49,13 +49,13 @@ LL | pub struct Bar<#[cold] const N: usize>;
|
|||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= help: `#[cold]` can only be applied to functions
|
= help: `#[cold]` can only be applied to functions
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-78957.rs:1:9
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:2:9
|
||||||
|
|
|
|
||||||
LL | #![deny(unused_attributes)]
|
LL | #![deny(unused_attributes)]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[cold]` attribute cannot be used on function params
|
error: `#[cold]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:15:17
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:16:17
|
||||||
|
|
|
|
||||||
LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
|
LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -64,7 +64,7 @@ LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
|
|||||||
= help: `#[cold]` can only be applied to functions
|
= help: `#[cold]` can only be applied to functions
|
||||||
|
|
||||||
error: `#[cold]` attribute cannot be used on function params
|
error: `#[cold]` attribute cannot be used on function params
|
||||||
--> $DIR/issue-78957.rs:23:17
|
--> $DIR/invalid-attributes-on-const-params-78957.rs:24:17
|
||||||
|
|
|
|
||||||
LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
|
LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/77218
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
fn main() {
|
fn main() {
|
||||||
let value = [7u8];
|
let value = [7u8];
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/77218
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
fn main() {
|
fn main() {
|
||||||
let value = [7u8];
|
let value = [7u8];
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0070]: invalid left-hand side of assignment
|
error[E0070]: invalid left-hand side of assignment
|
||||||
--> $DIR/issue-77218.rs:4:19
|
--> $DIR/invalid-assignment-in-while-loop-77218.rs:5:19
|
||||||
|
|
|
|
||||||
LL | while Some(0) = value.get(0) {}
|
LL | while Some(0) = value.get(0) {}
|
||||||
| - ^
|
| - ^
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/78192
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(unused_assignments)]
|
#![allow(unused_assignments)]
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/7660
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
// Regression test for issue 7660
|
// Regression test for issue 7660
|
||||||
// rvalue lifetime too short when equivalent `match` works
|
// rvalue lifetime too short when equivalent `match` works
|
||||||
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
struct A(isize, isize);
|
struct A(isize, isize);
|
||||||
@@ -6,6 +6,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
|||||||
|
|
|
|
||||||
= note: expected values for `target_feature` are: `10e60`
|
= note: expected values for `target_feature` are: `10e60`
|
||||||
`2e3`
|
`2e3`
|
||||||
|
`32s`
|
||||||
`3e3r1`
|
`3e3r1`
|
||||||
`3e3r2`
|
`3e3r2`
|
||||||
`3e3r3`
|
`3e3r3`
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/76042
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
//@ compile-flags: -Coverflow-checks=off -Ccodegen-units=1 -Copt-level=0
|
//@ compile-flags: -Coverflow-checks=off -Ccodegen-units=1 -Copt-level=0
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8248
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
|
|
||||||
trait A {
|
trait A {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
warning: method `dummy` is never used
|
warning: method `dummy` is never used
|
||||||
--> $DIR/issue-8248.rs:4:8
|
--> $DIR/mut-trait-coercion-8248.rs:5:8
|
||||||
|
|
|
|
||||||
LL | trait A {
|
LL | trait A {
|
||||||
| - method in this trait
|
| - method in this trait
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8398
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/76191
|
||||||
// Regression test for diagnostic issue #76191
|
// Regression test for diagnostic issue #76191
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
error[E0080]: evaluation panicked: explicit panic
|
error[E0080]: evaluation panicked: explicit panic
|
||||||
--> $DIR/issue-76191.rs:8:37
|
--> $DIR/const-range-matching-76191.rs:9:37
|
||||||
|
|
|
|
||||||
LL | const RANGE2: RangeInclusive<i32> = panic!();
|
LL | const RANGE2: RangeInclusive<i32> = panic!();
|
||||||
| ^^^^^^^^ evaluation of `RANGE2` failed here
|
| ^^^^^^^^ evaluation of `RANGE2` failed here
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-76191.rs:14:9
|
--> $DIR/const-range-matching-76191.rs:15:9
|
||||||
|
|
|
|
||||||
LL | const RANGE: RangeInclusive<i32> = 0..=255;
|
LL | const RANGE: RangeInclusive<i32> = 0..=255;
|
||||||
| -------------------------------- constant defined here
|
| -------------------------------- constant defined here
|
||||||
@@ -27,7 +27,7 @@ LL + 0..=255 => {}
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-76191.rs:16:9
|
--> $DIR/const-range-matching-76191.rs:17:9
|
||||||
|
|
|
|
||||||
LL | const RANGE2: RangeInclusive<i32> = panic!();
|
LL | const RANGE2: RangeInclusive<i32> = panic!();
|
||||||
| --------------------------------- constant defined here
|
| --------------------------------- constant defined here
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8259
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
//@ aux-build:issue-8259.rs
|
//@ aux-build:aux-8259.rs
|
||||||
|
|
||||||
|
extern crate aux_8259 as other;
|
||||||
extern crate issue_8259 as other;
|
|
||||||
static a: other::Foo<'static> = other::Foo::A;
|
static a: other::Foo<'static> = other::Foo::A;
|
||||||
|
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
10
tests/ui/cross-crate/tuple-like-structs-cross-crate-7899.rs
Normal file
10
tests/ui/cross-crate/tuple-like-structs-cross-crate-7899.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/7899
|
||||||
|
//@ run-pass
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
//@ aux-build:aux-7899.rs
|
||||||
|
|
||||||
|
extern crate aux_7899 as testcrate;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = testcrate::V2(1.0f32, 2.0f32);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//@ run-pass
|
||||||
|
//@ aux-build:aux-8401.rs
|
||||||
|
// https://github.com/rust-lang/rust/issues/8401
|
||||||
|
|
||||||
|
extern crate aux_8401;
|
||||||
|
|
||||||
|
pub fn main() {}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8761
|
||||||
enum Foo {
|
enum Foo {
|
||||||
A = 1i64,
|
A = 1i64,
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-8761.rs:2:9
|
--> $DIR/enum-discriminant-type-mismatch-8761.rs:3:9
|
||||||
|
|
|
|
||||||
LL | A = 1i64,
|
LL | A = 1i64,
|
||||||
| ^^^^ expected `isize`, found `i64`
|
| ^^^^ expected `isize`, found `i64`
|
||||||
@@ -11,7 +11,7 @@ LL + A = 1isize,
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-8761.rs:5:9
|
--> $DIR/enum-discriminant-type-mismatch-8761.rs:6:9
|
||||||
|
|
|
|
||||||
LL | B = 2u8
|
LL | B = 2u8
|
||||||
| ^^^ expected `isize`, found `u8`
|
| ^^^ expected `isize`, found `u8`
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/80607
|
||||||
// This tests makes sure the diagnostics print the offending enum variant, not just the type.
|
// This tests makes sure the diagnostics print the offending enum variant, not just the type.
|
||||||
pub enum Enum {
|
pub enum Enum {
|
||||||
V1(i32),
|
V1(i32),
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0559]: variant `Enum::V1` has no field named `x`
|
error[E0559]: variant `Enum::V1` has no field named `x`
|
||||||
--> $DIR/issue-80607.rs:7:16
|
--> $DIR/enum-variant-field-error-80607.rs:8:16
|
||||||
|
|
|
|
||||||
LL | V1(i32),
|
LL | V1(i32),
|
||||||
| -- `Enum::V1` defined here
|
| -- `Enum::V1` defined here
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/8506
|
||||||
//@ run-pass
|
//@ run-pass
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// https://github.com/rust-lang/rust/issues/75283
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn lol() { //~ ERROR incorrect function inside `extern` block
|
fn lol() { //~ ERROR incorrect function inside `extern` block
|
||||||
println!("");
|
println!("");
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user