Merge pull request #4211 from rust-lang/rustup-2025-02-26

Automatic Rustup
This commit is contained in:
Oli Scherer
2025-02-26 05:50:22 +00:00
committed by GitHub
81 changed files with 774 additions and 538 deletions

View File

@@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644
[dependencies]
core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] }
-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] }
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }

View File

@@ -460,64 +460,6 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
});
}
sym::simd_fpow => {
intrinsic_args!(fx, args => (a, b); intrinsic);
if !a.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
return;
}
simd_pair_for_each_lane(fx, a, b, ret, &|fx, lane_ty, _ret_lane_ty, a_lane, b_lane| {
match lane_ty.kind() {
ty::Float(FloatTy::F32) => fx.lib_call(
"powf",
vec![AbiParam::new(types::F32), AbiParam::new(types::F32)],
vec![AbiParam::new(types::F32)],
&[a_lane, b_lane],
)[0],
ty::Float(FloatTy::F64) => fx.lib_call(
"pow",
vec![AbiParam::new(types::F64), AbiParam::new(types::F64)],
vec![AbiParam::new(types::F64)],
&[a_lane, b_lane],
)[0],
_ => unreachable!("{:?}", lane_ty),
}
});
}
sym::simd_fpowi => {
intrinsic_args!(fx, args => (a, exp); intrinsic);
let exp = exp.load_scalar(fx);
if !a.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
return;
}
simd_for_each_lane(
fx,
a,
ret,
&|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() {
ty::Float(FloatTy::F32) => fx.lib_call(
"__powisf2", // compiler-builtins
vec![AbiParam::new(types::F32), AbiParam::new(types::I32)],
vec![AbiParam::new(types::F32)],
&[lane, exp],
)[0],
ty::Float(FloatTy::F64) => fx.lib_call(
"__powidf2", // compiler-builtins
vec![AbiParam::new(types::F64), AbiParam::new(types::I32)],
vec![AbiParam::new(types::F64)],
&[lane, exp],
)[0],
_ => unreachable!("{:?}", lane_ty),
},
);
}
sym::simd_fsin
| sym::simd_fcos
| sym::simd_fexp

View File

@@ -772,8 +772,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
sym::simd_floor => "floor",
sym::simd_fma => "fma",
sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
sym::simd_fpowi => "__builtin_powi",
sym::simd_fpow => "pow",
sym::simd_fsin => "sin",
sym::simd_fsqrt => "sqrt",
sym::simd_round => "round",
@@ -788,24 +786,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let mut vector_elements = vec![];
for i in 0..in_len {
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
// we have to treat fpowi specially, since fpowi's second argument is always an i32
let mut arguments = vec![];
if name == sym::simd_fpowi {
arguments = vec![
bx.extract_element(args[0].immediate(), index).to_rvalue(),
args[1].immediate(),
];
} else {
for arg in args {
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
// FIXME: it would probably be better to not have casts here and use the proper
// instructions.
if let Some(typ) = cast_type {
element = bx.context.new_cast(None, element, typ);
}
arguments.push(element);
for arg in args {
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
// FIXME: it would probably be better to not have casts here and use the proper
// instructions.
if let Some(typ) = cast_type {
element = bx.context.new_cast(None, element, typ);
}
};
arguments.push(element);
}
let mut result = bx.context.new_call(None, function, &arguments);
if cast_type.is_some() {
result = bx.context.new_cast(None, result, elem_ty);
@@ -829,8 +819,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
| sym::simd_floor
| sym::simd_fma
| sym::simd_relaxed_fma
| sym::simd_fpow
| sym::simd_fpowi
| sym::simd_fsin
| sym::simd_fsqrt
| sym::simd_round

View File

@@ -1581,8 +1581,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
@@ -1615,8 +1613,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
| sym::simd_flog
| sym::simd_floor
| sym::simd_fma
| sym::simd_fpow
| sym::simd_fpowi
| sym::simd_fsin
| sym::simd_fsqrt
| sym::simd_relaxed_fma

View File

@@ -2,6 +2,7 @@ use std::env;
use std::fmt::{Display, from_fn};
use std::num::ParseIntError;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::Session;
use rustc_target::spec::Target;
@@ -26,6 +27,89 @@ pub(super) fn macho_platform(target: &Target) -> u32 {
}
}
/// Add relocation and section data needed for a symbol to be considered
/// undefined by ld64.
///
/// The relocation must be valid, and hence must point to a valid piece of
/// machine code, and hence this is unfortunately very architecture-specific.
///
///
/// # New architectures
///
/// The values here are basically the same as emitted by the following program:
///
/// ```c
/// // clang -c foo.c -target $CLANG_TARGET
/// void foo(void);
///
/// extern int bar;
///
/// void* foobar[2] = {
/// (void*)foo,
/// (void*)&bar,
/// // ...
/// };
/// ```
///
/// Can be inspected with:
/// ```console
/// objdump --macho --reloc foo.o
/// objdump --macho --full-contents foo.o
/// ```
pub(super) fn add_data_and_relocation(
file: &mut object::write::Object<'_>,
section: object::write::SectionId,
symbol: object::write::SymbolId,
target: &Target,
kind: SymbolExportKind,
) -> object::write::Result<()> {
let authenticated_pointer =
kind == SymbolExportKind::Text && target.llvm_target.starts_with("arm64e");
let data: &[u8] = match target.pointer_width {
_ if authenticated_pointer => &[0, 0, 0, 0, 0, 0, 0, 0x80],
32 => &[0; 4],
64 => &[0; 8],
pointer_width => unimplemented!("unsupported Apple pointer width {pointer_width:?}"),
};
if target.arch == "x86_64" {
// Force alignment for the entire section to be 16 on x86_64.
file.section_mut(section).append_data(&[], 16);
} else {
// Elsewhere, the section alignment is the same as the pointer width.
file.section_mut(section).append_data(&[], target.pointer_width as u64);
}
let offset = file.section_mut(section).append_data(data, data.len() as u64);
let flags = if authenticated_pointer {
object::write::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_AUTHENTICATED_POINTER,
r_pcrel: false,
r_length: 3,
}
} else if target.arch == "arm" {
// FIXME(madsmtm): Remove once `object` supports 32-bit ARM relocations:
// https://github.com/gimli-rs/object/pull/757
object::write::RelocationFlags::MachO {
r_type: object::macho::ARM_RELOC_VANILLA,
r_pcrel: false,
r_length: 2,
}
} else {
object::write::RelocationFlags::Generic {
kind: object::RelocationKind::Absolute,
encoding: object::RelocationEncoding::Generic,
size: target.pointer_width as u8,
}
};
file.add_relocation(section, object::write::Relocation { offset, addend: 0, symbol, flags })?;
Ok(())
}
/// Deployment target or SDK version.
///
/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`.

View File

@@ -2058,8 +2058,8 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor
/// linker, and since they never participate in the linking, using `KEEP` in the linker scripts
/// can't keep them either. This causes #47384.
///
/// To keep them around, we could use `--whole-archive` and equivalents to force rlib to
/// participate in linking like object files, but this proves to be expensive (#93791). Therefore
/// To keep them around, we could use `--whole-archive`, `-force_load` and equivalents to force rlib
/// to participate in linking like object files, but this proves to be expensive (#93791). Therefore
/// we instead just introduce an undefined reference to them. This could be done by `-u` command
/// line option to the linker or `EXTERN(...)` in linker scripts, however they does not only
/// introduce an undefined reference, but also make them the GC roots, preventing `--gc-sections`
@@ -2101,8 +2101,20 @@ fn add_linked_symbol_object(
file.set_mangling(object::write::Mangling::None);
}
// ld64 requires a relocation to load undefined symbols, see below.
// Not strictly needed if linking with lld, but might as well do it there too.
let ld64_section_helper = if file.format() == object::BinaryFormat::MachO {
Some(file.add_section(
file.segment_name(object::write::StandardSegment::Data).to_vec(),
"__data".into(),
object::SectionKind::Data,
))
} else {
None
};
for (sym, kind) in symbols.iter() {
file.add_symbol(object::write::Symbol {
let symbol = file.add_symbol(object::write::Symbol {
name: sym.clone().into(),
value: 0,
size: 0,
@@ -2116,6 +2128,47 @@ fn add_linked_symbol_object(
section: object::write::SymbolSection::Undefined,
flags: object::SymbolFlags::None,
});
// The linker shipped with Apple's Xcode, ld64, works a bit differently from other linkers.
//
// Code-wise, the relevant parts of ld64 are roughly:
// 1. Find the `ArchiveLoadMode` based on commandline options, default to `parseObjects`.
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.cpp#L924-L932
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.h#L55
//
// 2. Read the archive table of contents (__.SYMDEF file).
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L294-L325
//
// 3. Begin linking by loading "atoms" from input files.
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/doc/design/linker.html
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1349
//
// a. Directly specified object files (`.o`) are parsed immediately.
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L4611-L4627
//
// - Undefined symbols are not atoms (`n_value > 0` denotes a common symbol).
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L2455-L2468
// https://maskray.me/blog/2022-02-06-all-about-common-symbols
//
// - Relocations/fixups are atoms.
// https://github.com/apple-oss-distributions/ld64/blob/ce6341ae966b3451aa54eeb049f2be865afbd578/src/ld/parsers/macho_relocatable_file.cpp#L2088-L2114
//
// b. Archives are not parsed yet.
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L467-L577
//
// 4. When a symbol is needed by an atom, parse the object file that contains the symbol.
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1417-L1491
// https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L579-L597
//
// All of the steps above are fairly similar to other linkers, except that **it completely
// ignores undefined symbols**.
//
// So to make this trick work on ld64, we need to do something else to load the relevant
// object files. We do this by inserting a relocation (fixup) for each symbol.
if let Some(section) = ld64_section_helper {
apple::add_data_and_relocation(&mut file, section, symbol, &sess.target, *kind)
.expect("failed adding relocation");
}
}
let path = tmpdir.join("symbols.o");

View File

@@ -15,7 +15,6 @@
#![feature(box_into_inner)]
#![feature(box_patterns)]
#![feature(error_reporter)]
#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(negative_impls)]

View File

@@ -1011,7 +1011,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
rustc_attr!(
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
"#![rustc_force_inline] forces a free function to be inlined"
"#[rustc_force_inline] forces a free function to be inlined"
),
// ==========================================================================

View File

@@ -605,6 +605,8 @@ hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
hir_analysis_unused_generic_parameter_ty_alias_help =
consider removing `{$param_name}` or referring to it in the body of the type alias
hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type
hir_analysis_value_of_associated_struct_already_specified =
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
.label = re-bound here

View File

@@ -992,6 +992,32 @@ fn check_impl_items_against_trait<'tcx>(
let trait_def = tcx.trait_def(trait_ref.def_id);
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id);
let param_env = tcx.param_env(impl_id);
let self_is_guaranteed_unsized = match tcx
.struct_tail_raw(
trait_ref.self_ty(),
|ty| {
ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
Ty::new_error_with_message(
tcx,
tcx.def_span(impl_id),
"struct tail should be computable",
)
})
},
|| (),
)
.kind()
{
ty::Dynamic(_, _, ty::DynKind::Dyn) | ty::Slice(_) | ty::Str => true,
_ => false,
};
for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
@@ -1021,6 +1047,15 @@ fn check_impl_items_against_trait<'tcx>(
}
}
if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) {
tcx.emit_node_span_lint(
rustc_lint_defs::builtin::DEAD_CODE,
tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
tcx.def_span(ty_impl_item.def_id),
errors::UselessImplItem,
)
}
check_specialization_validity(
tcx,
trait_def,
@@ -1044,7 +1079,11 @@ fn check_impl_items_against_trait<'tcx>(
.as_ref()
.is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
if !is_implemented && tcx.defaultness(impl_id).is_final() {
if !is_implemented
&& tcx.defaultness(impl_id).is_final()
// unsized types don't need to implement methods that have `Self: Sized` bounds.
&& !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id))
{
missing_items.push(tcx.associated_item(trait_item_id));
}

View File

@@ -645,7 +645,6 @@ pub fn check_intrinsic_type(
| sym::simd_xor
| sym::simd_fmin
| sym::simd_fmax
| sym::simd_fpow
| sym::simd_saturating_add
| sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
@@ -668,7 +667,6 @@ pub fn check_intrinsic_type(
| sym::simd_floor
| sym::simd_round
| sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)),
sym::simd_fma | sym::simd_relaxed_fma => {
(1, 0, vec![param(0), param(0), param(0)], param(0))
}

View File

@@ -908,6 +908,10 @@ pub(crate) enum ImplNotMarkedDefault {
},
}
#[derive(LintDiagnostic)]
#[diag(hir_analysis_useless_impl_item)]
pub(crate) struct UselessImplItem;
#[derive(Diagnostic)]
#[diag(hir_analysis_missing_trait_item, code = E0046)]
pub(crate) struct MissingTraitItem {

View File

@@ -23,7 +23,7 @@ use rustc_middle::ty::{
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::{Ident, Span, Symbol, sym};
use rustc_span::{ExpnKind, Ident, MacroKind, Span, Symbol, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
use rustc_trait_selection::infer::InferCtxtExt;
@@ -1365,6 +1365,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.param_env,
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
))
&& !expr
.span
.macro_backtrace()
.any(|x| matches!(x.kind, ExpnKind::Macro(MacroKind::Attr | MacroKind::Derive, ..)))
{
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
@@ -1380,10 +1384,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
}
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
Applicability::MaybeIncorrect
);
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
Applicability::MaybeIncorrect
);
return true;
}

View File

@@ -1,7 +1,7 @@
use std::iter::repeat;
use std::ops::ControlFlow;
use hir::intravisit::Visitor;
use hir::intravisit::{self, Visitor};
use rustc_ast::Recovered;
use rustc_errors::{
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
@@ -9,6 +9,7 @@ use rustc_errors::{
use rustc_hir::{self as hir, HirIdSet};
use rustc_macros::LintDiagnostic;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::adjustment::Adjust;
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::Span;
@@ -160,7 +161,7 @@ impl IfLetRescope {
let lifetime_end = source_map.end_point(conseq.span);
if let ControlFlow::Break(significant_dropper) =
(FindSignificantDropper { cx }).visit_expr(init)
(FindSignificantDropper { cx }).check_if_let_scrutinee(init)
{
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
significant_droppers.push(significant_dropper);
@@ -363,96 +364,97 @@ enum SingleArmMatchBegin {
WithoutOpenBracket(Span),
}
struct FindSignificantDropper<'tcx, 'a> {
struct FindSignificantDropper<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
type Result = ControlFlow<Span>;
impl<'tcx> FindSignificantDropper<'_, 'tcx> {
/// Check the scrutinee of an `if let` to see if it promotes any temporary values
/// that would change drop order in edition 2024. Specifically, it checks the value
/// of the scrutinee itself, and also recurses into the expression to find any ref
/// exprs (or autoref) which would promote temporaries that would be scoped to the
/// end of this `if`.
fn check_if_let_scrutinee(&mut self, init: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
self.check_promoted_temp_with_drop(init)?;
self.visit_expr(init)
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
if self
/// Check that an expression is not a promoted temporary with a significant
/// drop impl.
///
/// An expression is a promoted temporary if it has an addr taken (i.e. `&expr` or autoref)
/// or is the scrutinee of the `if let`, *and* the expression is not a place
/// expr, and it has a significant drop.
fn check_promoted_temp_with_drop(&self, expr: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
if !expr.is_place_expr(|base| {
self.cx
.typeck_results()
.adjustments()
.get(base.hir_id)
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
}) && self
.cx
.typeck_results()
.expr_ty(expr)
.has_significant_drop(self.cx.tcx, self.cx.typing_env())
{
return ControlFlow::Break(expr.span);
}
match expr.kind {
hir::ExprKind::ConstBlock(_)
| hir::ExprKind::Lit(_)
| hir::ExprKind::Path(_)
| hir::ExprKind::Assign(_, _, _)
| hir::ExprKind::AssignOp(_, _, _)
| hir::ExprKind::Break(_, _)
| hir::ExprKind::Continue(_)
| hir::ExprKind::Ret(_)
| hir::ExprKind::Become(_)
| hir::ExprKind::InlineAsm(_)
| hir::ExprKind::OffsetOf(_, _)
| hir::ExprKind::Repeat(_, _)
| hir::ExprKind::Err(_)
| hir::ExprKind::Struct(_, _, _)
| hir::ExprKind::Closure(_)
| hir::ExprKind::Block(_, _)
| hir::ExprKind::DropTemps(_)
| hir::ExprKind::Loop(_, _, _, _) => ControlFlow::Continue(()),
hir::ExprKind::Tup(exprs) | hir::ExprKind::Array(exprs) => {
for expr in exprs {
self.visit_expr(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::Call(callee, args) => {
self.visit_expr(callee)?;
for expr in args {
self.visit_expr(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::MethodCall(_, receiver, args, _) => {
self.visit_expr(receiver)?;
for expr in args {
self.visit_expr(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => {
self.visit_expr(left)?;
self.visit_expr(right)
}
hir::ExprKind::Unary(_, expr)
| hir::ExprKind::Cast(expr, _)
| hir::ExprKind::Type(expr, _)
| hir::ExprKind::UnsafeBinderCast(_, expr, _)
| hir::ExprKind::Yield(expr, _)
| hir::ExprKind::AddrOf(_, _, expr)
| hir::ExprKind::Match(expr, _, _)
| hir::ExprKind::Field(expr, _)
| hir::ExprKind::Let(&hir::LetExpr {
init: expr,
span: _,
pat: _,
ty: _,
recovered: Recovered::No,
}) => self.visit_expr(expr),
hir::ExprKind::Let(_) => ControlFlow::Continue(()),
hir::ExprKind::If(cond, _, _) => {
if let hir::ExprKind::Let(hir::LetExpr {
init,
span: _,
pat: _,
ty: _,
recovered: Recovered::No,
}) = cond.kind
{
self.visit_expr(init)?;
}
ControlFlow::Continue(())
}
ControlFlow::Break(expr.span)
} else {
ControlFlow::Continue(())
}
}
}
impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> {
type Result = ControlFlow<Span>;
fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) -> Self::Result {
// Blocks introduce temporary terminating scope for all of its
// statements, so just visit the tail expr, skipping over any
// statements. This prevents false positives like `{ let x = &Drop; }`.
if let Some(expr) = b.expr { self.visit_expr(expr) } else { ControlFlow::Continue(()) }
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
// Check for promoted temporaries from autoref, e.g.
// `if let None = TypeWithDrop.as_ref() {} else {}`
// where `fn as_ref(&self) -> Option<...>`.
for adj in self.cx.typeck_results().expr_adjustments(expr) {
match adj.kind {
// Skip when we hit the first deref expr.
Adjust::Deref(_) => break,
Adjust::Borrow(_) => {
self.check_promoted_temp_with_drop(expr)?;
}
_ => {}
}
}
match expr.kind {
// Account for cases like `if let None = Some(&Drop) {} else {}`.
hir::ExprKind::AddrOf(_, _, expr) => {
self.check_promoted_temp_with_drop(expr)?;
intravisit::walk_expr(self, expr)
}
// `(Drop, ()).1` introduces a temporary and then moves out of
// part of it, therefore we should check it for temporaries.
// FIXME: This may have false positives if we move the part
// that actually has drop, but oh well.
hir::ExprKind::Index(expr, _, _) | hir::ExprKind::Field(expr, _) => {
self.check_promoted_temp_with_drop(expr)?;
intravisit::walk_expr(self, expr)
}
// If always introduces a temporary terminating scope for its cond and arms,
// so don't visit them.
hir::ExprKind::If(..) => ControlFlow::Continue(()),
// Match introduces temporary terminating scopes for arms, so don't visit
// them, and only visit the scrutinee to account for cases like:
// `if let None = match &Drop { _ => Some(1) } {} else {}`.
hir::ExprKind::Match(scrut, _, _) => self.visit_expr(scrut),
// Self explanatory.
hir::ExprKind::DropTemps(_) => ControlFlow::Continue(()),
// Otherwise, walk into the expr's parts.
_ => intravisit::walk_expr(self, expr),
}
}
}

View File

@@ -26,7 +26,6 @@
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(iter_order_by)]
#![feature(let_chains)]

View File

@@ -5,7 +5,6 @@
#![feature(coroutines)]
#![feature(decl_macro)]
#![feature(error_iter)]
#![feature(extract_if)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]

View File

@@ -44,7 +44,6 @@
#![feature(decl_macro)]
#![feature(discriminant_kind)]
#![feature(extern_types)]
#![feature(extract_if)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]

View File

@@ -15,7 +15,6 @@
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]

View File

@@ -68,9 +68,7 @@ cfg_match! {
const CHUNK_SIZE: usize = 16;
let src_bytes = src.as_bytes();
let chunk_count = src.len() / CHUNK_SIZE;
let (chunks, tail) = src.as_bytes().as_chunks::<CHUNK_SIZE>();
// This variable keeps track of where we should start decoding a
// chunk. If a multi-byte character spans across chunk boundaries,
@@ -78,11 +76,10 @@ cfg_match! {
// handled it.
let mut intra_chunk_offset = 0;
for chunk_index in 0..chunk_count {
let ptr = src_bytes.as_ptr() as *const __m128i;
for (chunk_index, chunk) in chunks.iter().enumerate() {
// We don't know if the pointer is aligned to 16 bytes, so we
// use `loadu`, which supports unaligned loading.
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
let chunk = unsafe { _mm_loadu_si128(chunk.as_ptr() as *const __m128i) };
// For character in the chunk, see if its byte value is < 0, which
// indicates that it's part of a UTF-8 char.
@@ -123,7 +120,7 @@ cfg_match! {
}
// There might still be a tail left to analyze
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
let tail_start = src.len() - tail.len() + intra_chunk_offset;
if tail_start < src.len() {
analyze_source_file_generic(
&src[tail_start..],

View File

@@ -31,6 +31,7 @@
#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(slice_as_chunks)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end

View File

@@ -1877,8 +1877,6 @@ symbols! {
simd_fma,
simd_fmax,
simd_fmin,
simd_fpow,
simd_fpowi,
simd_fsin,
simd_fsqrt,
simd_gather,

View File

@@ -2914,20 +2914,35 @@ impl Target {
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
// `__stdcall` only applies on x86 and on non-variadic functions:
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
Stdcall { unwind }
System { unwind } => {
if self.is_like_windows && self.arch == "x86" && !c_variadic {
Stdcall { unwind }
} else {
C { unwind }
}
}
EfiApi => {
if self.arch == "arm" {
Aapcs { unwind: false }
} else if self.arch == "x86_64" {
Win64 { unwind: false }
} else {
C { unwind: false }
}
}
System { unwind } => C { unwind },
EfiApi if self.arch == "arm" => Aapcs { unwind: false },
EfiApi if self.arch == "x86_64" => Win64 { unwind: false },
EfiApi => C { unwind: false },
// See commentary in `is_abi_supported`.
Stdcall { .. } | Thiscall { .. } if self.arch == "x86" => abi,
Stdcall { unwind } | Thiscall { unwind } => C { unwind },
Fastcall { .. } if self.arch == "x86" => abi,
Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
Fastcall { unwind } | Vectorcall { unwind } => C { unwind },
Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => {
if self.arch == "x86" { abi } else { C { unwind } }
}
Vectorcall { unwind } => {
if ["x86", "x86_64"].contains(&&*self.arch) {
abi
} else {
C { unwind }
}
}
// The Windows x64 calling convention we use for `extern "Rust"`
// <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>

View File

@@ -20,7 +20,6 @@
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(cfg_version)]
#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(iterator_try_reduce)]

View File

@@ -131,8 +131,6 @@ pub struct TraitPredicate<I: Interner> {
/// If polarity is Negative: we are proving that a negative impl of this trait
/// exists. (Note that coherence also checks whether negative impls of supertraits
/// exist via a series of predicates.)
///
/// If polarity is Reserved: that's a bug.
pub polarity: PredicatePolarity,
}

View File

@@ -61,9 +61,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
version = "0.1.147"
version = "0.1.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170335a76fbcba350c3ea795c15df3b2c02934e35e502e82c4dd7837d4d0161"
checksum = "26137996631d90d2727b905b480fdcf8c4479fdbce7afd7f8e3796d689b33cc2"
dependencies = [
"cc",
"rustc-std-workspace-core",

View File

@@ -12,7 +12,7 @@ edition = "2021"
[dependencies]
core = { path = "../core", public = true }
compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
[dev-dependencies]
rand = { version = "0.9.0", default-features = false, features = ["alloc"] }

View File

@@ -289,7 +289,7 @@ impl<K: Clone, V: Clone, A: Allocator + Clone> Clone for BTreeMap<K, V, A> {
}
}
/// Internal functionality for `BTreeSet`.
// Internal functionality for `BTreeSet`.
impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
pub(super) fn replace(&mut self, key: K) -> Option<K>
where

View File

@@ -1140,7 +1140,6 @@ impl<T, A: Allocator> LinkedList<T, A> {
/// Splitting a list into evens and odds, reusing the original list:
///
/// ```
/// #![feature(extract_if)]
/// use std::collections::LinkedList;
///
/// let mut numbers: LinkedList<u32> = LinkedList::new();
@@ -1152,7 +1151,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]);
/// ```
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,
@@ -1932,7 +1931,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
}
/// An iterator produced by calling `extract_if` on LinkedList.
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
'a,
@@ -1947,7 +1946,7 @@ pub struct ExtractIf<
old_len: usize,
}
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,
@@ -1976,7 +1975,7 @@ where
}
}
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T: fmt::Debug, F> fmt::Debug for ExtractIf<'_, T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ExtractIf").field(&self.list).finish()

View File

@@ -966,11 +966,8 @@ impl String {
/// This is highly unsafe, due to the number of invariants that aren't
/// checked:
///
/// * The memory at `buf` needs to have been previously allocated by the
/// same allocator the standard library uses, with a required alignment of exactly 1.
/// * `length` needs to be less than or equal to `capacity`.
/// * `capacity` needs to be the correct value.
/// * The first `length` bytes at `buf` need to be valid UTF-8.
/// * all safety requirements for [`Vec::<u8>::from_raw_parts`].
/// * all safety requirements for [`String::from_utf8_unchecked`].
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures. For example, it is normally **not** safe to

View File

@@ -12,12 +12,10 @@ use crate::alloc::{Allocator, Global};
/// # Example
///
/// ```
/// #![feature(extract_if)]
///
/// let mut v = vec![0, 1, 2];
/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0);
/// ```
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
#[derive(Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
@@ -59,7 +57,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> {
}
}
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,
@@ -95,7 +93,7 @@ where
}
}
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A> {
fn drop(&mut self) {
unsafe {

View File

@@ -66,7 +66,7 @@ use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
use core::{fmt, intrinsics};
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
pub use self::extract_if::ExtractIf;
use crate::alloc::{Allocator, Global};
use crate::borrow::{Cow, ToOwned};
@@ -355,11 +355,20 @@ mod spec_extend;
/// and it may prove desirable to use a non-constant growth factor. Whatever
/// strategy is used will of course guarantee *O*(1) amortized [`push`].
///
/// `vec![x; n]`, `vec![a, b, c, d]`, and
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
/// with at least the requested capacity. If <code>[len] == [capacity]</code>,
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
/// It is guaranteed, in order to respect the intentions of the programmer, that
/// all of `vec![e_1, e_2, ..., e_n]`, `vec![x; n]`, and [`Vec::with_capacity(n)`] produce a `Vec`
/// that requests an allocation of the exact size needed for precisely `n` elements from the allocator,
/// and no other size (such as, for example: a size rounded up to the nearest power of 2).
/// The allocator will return an allocation that is at least as large as requested, but it may be larger.
///
/// It is guaranteed that the [`Vec::capacity`] method returns a value that is at least the requested capacity
/// and not more than the allocated capacity.
///
/// The method [`Vec::shrink_to_fit`] will attempt to discard excess capacity an allocator has given to a `Vec`.
/// If <code>[len] == [capacity]</code>, then a `Vec<T>` can be converted
/// to and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
/// `Vec` exploits this fact as much as reasonable when implementing common conversions
/// such as [`into_boxed_slice`].
///
/// `Vec` will not specifically overwrite any data that is removed from it,
/// but also won't specifically preserve it. Its uninitialized memory is
@@ -383,14 +392,17 @@ mod spec_extend;
/// [`shrink_to`]: Vec::shrink_to
/// [capacity]: Vec::capacity
/// [`capacity`]: Vec::capacity
/// [`Vec::capacity`]: Vec::capacity
/// [mem::size_of::\<T>]: core::mem::size_of
/// [len]: Vec::len
/// [`len`]: Vec::len
/// [`push`]: Vec::push
/// [`insert`]: Vec::insert
/// [`reserve`]: Vec::reserve
/// [`Vec::with_capacity(n)`]: Vec::with_capacity
/// [`MaybeUninit`]: core::mem::MaybeUninit
/// [owned slice]: Box
/// [`into_boxed_slice`]: Vec::into_boxed_slice
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")]
#[rustc_insignificant_dtor]
@@ -3684,7 +3696,6 @@ impl<T, A: Allocator> Vec<T, A> {
/// Splitting an array into evens and odds, reusing the original allocation:
///
/// ```
/// #![feature(extract_if)]
/// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
///
/// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
@@ -3697,13 +3708,12 @@ impl<T, A: Allocator> Vec<T, A> {
/// Using the range argument to only process a part of the vector:
///
/// ```
/// #![feature(extract_if)]
/// let mut items = vec![0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2];
/// let ones = items.extract_if(7.., |x| *x == 1).collect::<Vec<_>>();
/// assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]);
/// assert_eq!(ones.len(), 3);
/// ```
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F, R>(&mut self, range: R, filter: F) -> ExtractIf<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,

View File

@@ -7,7 +7,6 @@
#![feature(cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(downcast_unchecked)]
#![feature(extract_if)]
#![feature(exact_size_is_empty)]
#![feature(hashmap_internals)]
#![feature(linked_list_cursors)]
@@ -29,7 +28,6 @@
#![feature(string_remove_matches)]
#![feature(const_btree_len)]
#![feature(const_trait_impl)]
#![feature(const_str_from_utf8)]
#![feature(panic_update_hook)]
#![feature(pointer_is_aligned_to)]
#![feature(test)]

View File

@@ -1041,7 +1041,6 @@ impl<T> MaybeUninit<T> {
/// Deprecated version of [`slice::assume_init_ref`].
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[deprecated(
note = "replaced by inherent assume_init_ref method; will eventually be removed",
since = "1.83.0"
@@ -1053,7 +1052,6 @@ impl<T> MaybeUninit<T> {
/// Deprecated version of [`slice::assume_init_mut`].
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[deprecated(
note = "replaced by inherent assume_init_mut method; will eventually be removed",
since = "1.83.0"
@@ -1326,7 +1324,6 @@ impl<T> [MaybeUninit<T>] {
///
/// [`write_clone_of_slice`]: slice::write_clone_of_slice
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
#[rustc_const_unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T]
where
T: Copy,

View File

@@ -956,7 +956,6 @@ impl<T> [T] {
/// [`swap`]: slice::swap
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
#[unstable(feature = "slice_swap_unchecked", issue = "88539")]
#[rustc_const_unstable(feature = "slice_swap_unchecked", issue = "88539")]
pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
assert_unsafe_precondition!(
check_library_ub,
@@ -3734,6 +3733,7 @@ impl<T> [T] {
#[inline]
#[stable(feature = "copy_from_slice", since = "1.9.0")]
#[rustc_const_unstable(feature = "const_copy_from_slice", issue = "131415")]
#[rustc_const_stable_indirect]
#[track_caller]
pub const fn copy_from_slice(&mut self, src: &[T])
where

View File

@@ -126,7 +126,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
/// See the docs for [`Utf8Error`] for more details on the kinds of
/// errors that can be returned.
#[stable(feature = "str_mut_extras", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
#[rustc_const_stable(feature = "const_str_from_utf8", since = "CURRENT_RUSTC_VERSION")]
#[rustc_diagnostic_item = "str_from_utf8_mut"]
pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
// FIXME(const-hack): This should use `?` again, once it's `const`

View File

@@ -265,7 +265,7 @@ impl str {
/// See the docs for [`Utf8Error`] for more details on the kinds of
/// errors that can be returned.
#[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
#[rustc_const_stable(feature = "const_str_from_utf8", since = "CURRENT_RUSTC_VERSION")]
#[rustc_diagnostic_item = "str_inherent_from_utf8_mut"]
pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
converts::from_utf8_mut(v)

View File

@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
compiler_builtins = { version = "=0.1.147" }
compiler_builtins = { version = "=0.1.148" }
unwind = { path = "../unwind" }
hashbrown = { version = "0.15", default-features = false, features = [
'rustc-dep-of-std',

View File

@@ -656,7 +656,6 @@ impl<K, V, S> HashMap<K, V, S> {
/// Splitting a map into even and odd keys, reusing the original map:
///
/// ```
/// #![feature(hash_extract_if)]
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
@@ -672,7 +671,7 @@ impl<K, V, S> HashMap<K, V, S> {
/// ```
#[inline]
#[rustc_lint_query_instability]
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F>
where
F: FnMut(&K, &mut V) -> bool,
@@ -1722,8 +1721,6 @@ impl<'a, K, V> Drain<'a, K, V> {
/// # Example
///
/// ```
/// #![feature(hash_extract_if)]
///
/// use std::collections::HashMap;
///
/// let mut map = HashMap::from([
@@ -1731,7 +1728,7 @@ impl<'a, K, V> Drain<'a, K, V> {
/// ]);
/// let iter = map.extract_if(|_k, v| *v % 2 == 0);
/// ```
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<'a, K, V, F>
where
@@ -2746,7 +2743,7 @@ where
}
}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, V, F> Iterator for ExtractIf<'_, K, V, F>
where
F: FnMut(&K, &mut V) -> bool,
@@ -2763,10 +2760,10 @@ where
}
}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<'a, K, V, F> fmt::Debug for ExtractIf<'a, K, V, F>
where
F: FnMut(&K, &mut V) -> bool,

View File

@@ -293,7 +293,6 @@ impl<T, S> HashSet<T, S> {
/// Splitting a set into even and odd values, reusing the original set:
///
/// ```
/// #![feature(hash_extract_if)]
/// use std::collections::HashSet;
///
/// let mut set: HashSet<i32> = (0..8).collect();
@@ -309,7 +308,7 @@ impl<T, S> HashSet<T, S> {
/// ```
#[inline]
#[rustc_lint_query_instability]
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, T, F>
where
F: FnMut(&T) -> bool,
@@ -1385,15 +1384,13 @@ pub struct Drain<'a, K: 'a> {
/// # Examples
///
/// ```
/// #![feature(hash_extract_if)]
///
/// use std::collections::HashSet;
///
/// let mut a = HashSet::from([1, 2, 3]);
///
/// let mut extract_ifed = a.extract_if(|v| v % 2 == 0);
/// ```
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
pub struct ExtractIf<'a, K, F>
where
F: FnMut(&K) -> bool,
@@ -1676,7 +1673,7 @@ impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
}
}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, F> Iterator for ExtractIf<'_, K, F>
where
F: FnMut(&K) -> bool,
@@ -1693,10 +1690,10 @@ where
}
}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, F> FusedIterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool {}
#[unstable(feature = "hash_extract_if", issue = "59618")]
#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<'a, K, F> fmt::Debug for ExtractIf<'a, K, F>
where
F: FnMut(&K) -> bool,

View File

@@ -1,6 +1,6 @@
use super::abi;
use super::abi::fileno;
use crate::io;
use crate::io::{self, BorrowedCursor};
pub struct Stdin;
pub struct Stdout;
@@ -16,6 +16,14 @@ impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
Ok(unsafe { abi::sys_read(fileno::STDIN, buf.as_mut_ptr(), buf.len()) })
}
fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> {
unsafe {
let n = abi::sys_read(fileno::STDIN, buf.as_mut().as_mut_ptr().cast(), buf.capacity());
buf.advance_unchecked(n);
}
Ok(())
}
}
impl Stdout {

View File

@@ -88,9 +88,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.0"
version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
dependencies = [
"shlex",
]

View File

@@ -37,7 +37,9 @@ test = false
# Most of the time updating these dependencies requires modifications to the
# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
cc = "=1.2.0"
#
# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
cc = "=1.1.22"
cmake = "=0.1.48"
build_helper = { path = "../build_helper" }

View File

@@ -776,6 +776,6 @@ if __name__ == "__main__":
f.write(contents)
p("")
p("run `python {}/x.py --help`".format(rust_dir))
p("run `{} {}/x.py --help`".format(os.path.basename(sys.executable), rust_dir))
if "GITHUB_ACTIONS" in os.environ:
print("::endgroup::")

View File

@@ -293,17 +293,27 @@ impl Step for Cargo {
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Cargo { stage: run.builder.top_stage, host: run.target });
// If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2
// as tests for this step don't work with a lower stage.
let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
run.builder.top_stage
} else {
2
};
run.builder.ensure(Cargo { stage, host: run.target });
}
/// Runs `cargo test` for `cargo` packaged with Rust.
fn run(self, builder: &Builder<'_>) {
if self.stage < 2 {
eprintln!("WARNING: cargo tests on stage {} may not behave well.", self.stage);
let stage = self.stage;
if stage < 2 {
eprintln!("WARNING: cargo tests on stage {stage} may not behave well.");
eprintln!("HELP: consider using stage 2");
}
let compiler = builder.compiler(self.stage, self.host);
let compiler = builder.compiler(stage, self.host);
let cargo = builder.ensure(tool::Cargo { compiler, target: self.host });
let compiler = cargo.build_compiler;
@@ -340,7 +350,7 @@ impl Step for Cargo {
crates: vec!["cargo".into()],
target: self.host.triple.to_string(),
host: self.host.triple.to_string(),
stage: self.stage,
stage,
},
builder,
);
@@ -739,7 +749,15 @@ impl Step for Clippy {
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Clippy { stage: run.builder.top_stage, host: run.target });
// If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2
// as tests for this step don't work with a lower stage.
let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
run.builder.top_stage
} else {
2
};
run.builder.ensure(Clippy { stage, host: run.target });
}
/// Runs `cargo test` for clippy.

View File

@@ -218,6 +218,8 @@ pub struct Config {
pub stderr_is_tty: bool,
pub on_fail: Option<String>,
pub explicit_stage_from_cli: bool,
pub explicit_stage_from_config: bool,
pub stage: u32,
pub keep_stage: Vec<u32>,
pub keep_stage_std: Vec<u32>,
@@ -2323,6 +2325,14 @@ impl Config {
config.compiletest_diff_tool = compiletest_diff_tool;
let download_rustc = config.download_rustc_commit.is_some();
config.explicit_stage_from_cli = flags.stage.is_some();
config.explicit_stage_from_config = test_stage.is_some()
|| build_stage.is_some()
|| doc_stage.is_some()
|| dist_stage.is_some()
|| install_stage.is_some()
|| check_stage.is_some()
|| bench_stage.is_some();
// See https://github.com/rust-lang/compiler-team/issues/326
config.stage = match config.cmd {
Subcommand::Check { .. } => flags.stage.or(check_stage).unwrap_or(0),
@@ -2392,6 +2402,10 @@ impl Config {
}
}
pub fn is_explicit_stage(&self) -> bool {
self.explicit_stage_from_cli || self.explicit_stage_from_config
}
/// Runs a command, printing out nice contextual information if it fails.
/// Exits if the command failed to execute at all, otherwise returns its
/// `status.success()`.

View File

@@ -454,3 +454,64 @@ fn check_rustc_if_unchanged_paths() {
assert!(config.src.join(p).exists(), "{p} doesn't exist.");
}
}
#[test]
fn test_explicit_stage() {
let config = Config::parse_inner(
Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
|&_| {
toml::from_str(
r#"
[build]
test-stage = 1
"#,
)
},
);
assert!(!config.explicit_stage_from_cli);
assert!(config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
let config = Config::parse_inner(
Flags::parse(&[
"check".to_owned(),
"--stage=2".to_owned(),
"--config=/does/not/exist".to_owned(),
]),
|&_| toml::from_str(""),
);
assert!(config.explicit_stage_from_cli);
assert!(!config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
let config = Config::parse_inner(
Flags::parse(&[
"check".to_owned(),
"--stage=2".to_owned(),
"--config=/does/not/exist".to_owned(),
]),
|&_| {
toml::from_str(
r#"
[build]
test-stage = 1
"#,
)
},
);
assert!(config.explicit_stage_from_cli);
assert!(config.explicit_stage_from_config);
assert!(config.is_explicit_stage());
let config = Config::parse_inner(
Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
|&_| toml::from_str(""),
);
assert!(!config.explicit_stage_from_cli);
assert!(!config.explicit_stage_from_config);
assert!(!config.is_explicit_stage());
}

View File

@@ -154,7 +154,6 @@ pub fn get_closest_merge_commit(
"rev-list",
&format!("--author={}", config.git_merge_commit_email),
"-n1",
"--first-parent",
&merge_base,
]);

View File

@@ -1 +1 @@
f5729cfed3c45e061e8a443677fc1d5ef9277df7
cb06d12710575a0d7ff71d6fe108f3bcff4f9195

View File

@@ -251,11 +251,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = apply_random_float_error_ulp(
this,
res,
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = apply_random_float_error_ulp(
// this,
// res,
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?;
}
@@ -286,11 +287,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = apply_random_float_error_ulp(
this,
res,
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = apply_random_float_error_ulp(
// this,
// res,
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?;
}

View File

@@ -16,7 +16,6 @@
#![feature(unqualified_local_imports)]
#![feature(derive_coerce_pointee)]
#![feature(arbitrary_self_types)]
#![feature(extract_if)]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,

View File

@@ -765,13 +765,15 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"erfcf" => f_host.erfc(),
_ => bug!(),
};
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = math::apply_random_float_error_ulp(
this,
res.to_soft(),
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(
// this,
// res,
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?;
}
@@ -796,11 +798,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
};
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = math::apply_random_float_error_ulp(
this,
res,
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(
// this,
// res,
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f1, f2]);
this.write_scalar(res, dest)?;
}
@@ -839,13 +842,15 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"erfc" => f_host.erfc(),
_ => bug!(),
};
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = math::apply_random_float_error_ulp(
this,
res.to_soft(),
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(
// this,
// res.to_soft(),
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?;
}
@@ -870,11 +875,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
};
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res = math::apply_random_float_error_ulp(
this,
res,
4, // log2(16)
);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(
// this,
// res,
// 4, // log2(16)
// );
let res = this.adjust_nan(res, &[f1, f2]);
this.write_scalar(res, dest)?;
}
@@ -900,10 +906,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Using host floats (but it's fine, these operations do not have guaranteed precision).
let (res, sign) = x.to_host().ln_gamma();
this.write_int(sign, &signp)?;
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res =
math::apply_random_float_error_ulp(this, res.to_soft(), 4 /* log2(16) */);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(this, res, 4 /* log2(16) */);
let res = this.adjust_nan(res, &[x]);
this.write_scalar(res, dest)?;
}
@@ -915,10 +922,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Using host floats (but it's fine, these operations do not have guaranteed precision).
let (res, sign) = x.to_host().ln_gamma();
this.write_int(sign, &signp)?;
let res = res.to_soft();
// Apply a relative error of 16ULP to introduce some non-determinism
// simulating imprecise implementations and optimizations.
let res =
math::apply_random_float_error_ulp(this, res.to_soft(), 4 /* log2(16) */);
// FIXME: temporarily disabled as it breaks std tests.
// let res = math::apply_random_float_error_ulp(this, res, 4 /* log2(16) */);
let res = this.adjust_nan(res, &[x]);
this.write_scalar(res, dest)?;
}

View File

@@ -1290,7 +1290,8 @@ fn test_non_determinism() {
}
}
// We saw the same thing N times.
panic!("expected non-determinism, got {rounds} times the same result: {first:?}");
// FIXME: temporarily disabled as it breaks std tests.
//panic!("expected non-determinism, got {rounds} times the same result: {first:?}");
}
macro_rules! test_operations_f {

View File

@@ -1,87 +0,0 @@
//@ compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
#![feature(repr_simd, intrinsics)]
#![allow(non_camel_case_types)]
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
extern "rust-intrinsic" {
fn simd_fpow<T>(x: T, b: T) -> T;
}
// CHECK-LABEL: @fpow_32x2
#[no_mangle]
pub unsafe fn fpow_32x2(a: f32x2, b: f32x2) -> f32x2 {
// CHECK: call <2 x float> @llvm.pow.v2f32
simd_fpow(a, b)
}
// CHECK-LABEL: @fpow_32x4
#[no_mangle]
pub unsafe fn fpow_32x4(a: f32x4, b: f32x4) -> f32x4 {
// CHECK: call <4 x float> @llvm.pow.v4f32
simd_fpow(a, b)
}
// CHECK-LABEL: @fpow_32x8
#[no_mangle]
pub unsafe fn fpow_32x8(a: f32x8, b: f32x8) -> f32x8 {
// CHECK: call <8 x float> @llvm.pow.v8f32
simd_fpow(a, b)
}
// CHECK-LABEL: @fpow_32x16
#[no_mangle]
pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 {
// CHECK: call <16 x float> @llvm.pow.v16f32
simd_fpow(a, b)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fpow_64x4
#[no_mangle]
pub unsafe fn fpow_64x4(a: f64x4, b: f64x4) -> f64x4 {
// CHECK: call <4 x double> @llvm.pow.v4f64
simd_fpow(a, b)
}
// CHECK-LABEL: @fpow_64x2
#[no_mangle]
pub unsafe fn fpow_64x2(a: f64x2, b: f64x2) -> f64x2 {
// CHECK: call <2 x double> @llvm.pow.v2f64
simd_fpow(a, b)
}
// CHECK-LABEL: @fpow_64x8
#[no_mangle]
pub unsafe fn fpow_64x8(a: f64x8, b: f64x8) -> f64x8 {
// CHECK: call <8 x double> @llvm.pow.v8f64
simd_fpow(a, b)
}

View File

@@ -1,87 +0,0 @@
//@ compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
#![feature(repr_simd, intrinsics)]
#![allow(non_camel_case_types)]
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x2(pub [f32; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x4(pub [f32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x8(pub [f32; 8]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f32x16(pub [f32; 16]);
extern "rust-intrinsic" {
fn simd_fpowi<T>(x: T, b: i32) -> T;
}
// CHECK-LABEL: @fpowi_32x2
#[no_mangle]
pub unsafe fn fpowi_32x2(a: f32x2, b: i32) -> f32x2 {
// CHECK: call <2 x float> @llvm.powi.v2f32
simd_fpowi(a, b)
}
// CHECK-LABEL: @fpowi_32x4
#[no_mangle]
pub unsafe fn fpowi_32x4(a: f32x4, b: i32) -> f32x4 {
// CHECK: call <4 x float> @llvm.powi.v4f32
simd_fpowi(a, b)
}
// CHECK-LABEL: @fpowi_32x8
#[no_mangle]
pub unsafe fn fpowi_32x8(a: f32x8, b: i32) -> f32x8 {
// CHECK: call <8 x float> @llvm.powi.v8f32
simd_fpowi(a, b)
}
// CHECK-LABEL: @fpowi_32x16
#[no_mangle]
pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 {
// CHECK: call <16 x float> @llvm.powi.v16f32
simd_fpowi(a, b)
}
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x2(pub [f64; 2]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x4(pub [f64; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct f64x8(pub [f64; 8]);
// CHECK-LABEL: @fpowi_64x4
#[no_mangle]
pub unsafe fn fpowi_64x4(a: f64x4, b: i32) -> f64x4 {
// CHECK: call <4 x double> @llvm.powi.v4f64
simd_fpowi(a, b)
}
// CHECK-LABEL: @fpowi_64x2
#[no_mangle]
pub unsafe fn fpowi_64x2(a: f64x2, b: i32) -> f64x2 {
// CHECK: call <2 x double> @llvm.powi.v2f64
simd_fpowi(a, b)
}
// CHECK-LABEL: @fpowi_64x8
#[no_mangle]
pub unsafe fn fpowi_64x8(a: f64x8, b: i32) -> f64x8 {
// CHECK: call <8 x double> @llvm.powi.v8f64
simd_fpowi(a, b)
}

View File

@@ -1,5 +1,6 @@
mod foo {
#[link_section = ".rodata.STATIC"]
#[cfg_attr(target_os = "linux", link_section = ".rodata.STATIC")]
#[cfg_attr(target_vendor = "apple", link_section = "__DATA,STATIC")]
#[used]
static STATIC: [u32; 10] = [1; 10];
}

View File

@@ -7,15 +7,20 @@
// See https://github.com/rust-lang/rust/pull/95604
// See https://github.com/rust-lang/rust/issues/47384
//@ only-linux
// Reason: differences in object file formats on OSX and Windows
// causes errors in the llvm_objdump step
//@ ignore-wasm differences in object file formats causes errors in the llvm_objdump step.
//@ ignore-windows differences in object file formats causes errors in the llvm_objdump step.
use run_make_support::{dynamic_lib_name, llvm_objdump, llvm_readobj, rustc};
use run_make_support::{dynamic_lib_name, llvm_objdump, llvm_readobj, rustc, target};
fn main() {
rustc().crate_type("lib").input("lib.rs").run();
rustc().crate_type("cdylib").link_args("-Tlinker.ld").input("main.rs").run();
let mut main = rustc();
main.crate_type("cdylib");
if target().contains("linux") {
main.link_args("-Tlinker.ld");
}
main.input("main.rs").run();
// Ensure `#[used]` and `KEEP`-ed section is there
llvm_objdump()
.arg("--full-contents")

View File

@@ -26,6 +26,8 @@ click: ".example-wrap .copy-button"
move-cursor-to: ".search-input"
assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
// Since we clicked on the copy button, the clipboard content should have been updated.
assert-clipboard: 'println!("nothing fancy");\nprintln!("but with two lines!");'
define-function: (
"check-buttons",

View File

@@ -1,12 +1,17 @@
// Checks that the "copy path" button is not triggering JS error and its display
// isn't broken.
go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
// isn't broken and the copied path is as expected.
go-to: "file://" + |DOC_PATH| + "/test_docs/foreign_impl_order/trait.Foo.html"
// We ensure that the clipboard is empty.
assert-clipboard: ""
// First we store the size of the button before we click on it.
store-size: ("#copy-path", {"width": width, "height": height})
click: "#copy-path"
// We wait for the new text to appear.
wait-for: "#copy-path.clicked"
// We check that the clipboard value is the expected one.
assert-clipboard: "test_docs::foreign_impl_order::Foo"
// We check that the size didn't change.
assert-size: ("#copy-path.clicked", {"width": |width|, "height": |height|})
// We wait for the button to turn back to its original state.

View File

@@ -0,0 +1,32 @@
//! Add a constructor that runs pre-main, similar to what the `ctor` crate does.
//!
//! #[ctor]
//! fn constructor() {
//! println!("constructor");
//! }
//@ no-prefer-dynamic explicitly test with crates that are built as an archive
#![crate_type = "rlib"]
#[cfg_attr(
any(
target_os = "linux",
target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
target_os = "haiku"
),
link_section = ".init_array"
)]
#[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func,mod_init_funcs")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
#[used]
static CONSTRUCTOR: extern "C" fn() = constructor;
#[cfg_attr(any(target_os = "linux", target_os = "android"), link_section = ".text.startup")]
extern "C" fn constructor() {
println!("constructor");
}

View File

@@ -0,0 +1,16 @@
//! Ensure that `#[used]` in archives are correctly registered.
//!
//! Regression test for https://github.com/rust-lang/rust/issues/133491.
//@ run-pass
//@ check-run-results
//@ aux-build: used_pre_main_constructor.rs
//@ ignore-wasm ctor doesn't work on WASM
// Make sure `rustc` links the archive, but intentionally do not import/use any items.
extern crate used_pre_main_constructor as _;
fn main() {
println!("main");
}

View File

@@ -0,0 +1,2 @@
constructor
main

View File

@@ -1,3 +1,7 @@
error: reached the recursion limit finding the struct tail for `K`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
error: reached the recursion limit finding the struct tail for `Bottom`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
@@ -21,7 +25,7 @@ LL | let x: &Bottom = &t;
= note: expected reference `&Bottom`
found reference `&Top`
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0055, E0308.
For more information about an error, try `rustc --explain E0055`.

View File

@@ -0,0 +1,33 @@
//@ edition: 2021
//@ check-pass
#![deny(if_let_rescope)]
struct Drop;
impl std::ops::Drop for Drop {
fn drop(&mut self) {
println!("drop")
}
}
impl Drop {
fn as_ref(&self) -> Option<i32> {
Some(1)
}
}
fn consume(_: impl Sized) -> Option<i32> { Some(1) }
fn main() {
let drop = Drop;
// Make sure we don't drop if we don't actually make a temporary.
if let None = drop.as_ref() {} else {}
// Make sure we don't lint if we consume the droppy value.
if let None = consume(Drop) {} else {}
// Make sure we don't lint on field exprs of place exprs.
let tup_place = (Drop, ());
if let None = consume(tup_place.1) {} else {}
}

View File

@@ -94,6 +94,12 @@ fn main() {
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
}
match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
// We want to keep the `if let`s below as direct descendents of match arms,
// so the formatting is suppressed.
#[rustfmt::skip]

View File

@@ -94,6 +94,12 @@ fn main() {
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
}
if let Some(_value) = Some((droppy(), ()).1) {} else {}
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: the value is now dropped here in Edition 2024
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
// We want to keep the `if let`s below as direct descendents of match arms,
// so the formatting is suppressed.
#[rustfmt::skip]

View File

@@ -175,5 +175,26 @@ LL - while (if let Some(_value) = droppy().get() { false } else { true }) {
LL + while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
|
error: aborting due to 7 previous errors
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:97:8
|
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
| ^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^
| |
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:97:51
|
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
| ^
help: a `match` with a single arm can preserve the drop order up to Edition 2021
|
LL - if let Some(_value) = Some((droppy(), ()).1) {} else {}
LL + match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
|
error: aborting due to 8 previous errors

View File

@@ -2,11 +2,11 @@
#![allow(internal_features)]
#[rustc_force_inline]
//~^ ERROR #![rustc_force_inline] forces a free function to be inlined
//~^ ERROR #[rustc_force_inline] forces a free function to be inlined
pub fn bare() {
}
#[rustc_force_inline = "the test requires it"]
//~^ ERROR #![rustc_force_inline] forces a free function to be inlined
//~^ ERROR #[rustc_force_inline] forces a free function to be inlined
pub fn justified() {
}

View File

@@ -1,4 +1,4 @@
error[E0658]: #![rustc_force_inline] forces a free function to be inlined
error[E0658]: #[rustc_force_inline] forces a free function to be inlined
--> $DIR/gate.rs:4:1
|
LL | #[rustc_force_inline]
@@ -7,7 +7,7 @@ LL | #[rustc_force_inline]
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: #![rustc_force_inline] forces a free function to be inlined
error[E0658]: #[rustc_force_inline] forces a free function to be inlined
--> $DIR/gate.rs:9:1
|
LL | #[rustc_force_inline = "the test requires it"]

View File

@@ -1,6 +1,6 @@
//@ build-fail
//@ check-fail
//@ compile-flags: --crate-type lib -Cdebuginfo=2
//@ error-pattern: the type has an unknown layout
//@ error-pattern: recursion limit
#![recursion_limit = "10"]
macro_rules! link {
@@ -28,7 +28,6 @@ impl Bottom {
}
}
link!(A, B);
link!(B, C);
link!(C, D);
@@ -41,4 +40,4 @@ link!(I, J);
link!(J, K);
link!(K, Bottom);
fn main() { }
fn main() {}

View File

@@ -2,7 +2,5 @@ error: reached the recursion limit finding the struct tail for `Bottom`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
error: the type has an unknown layout
error: aborting due to 2 previous errors
error: aborting due to 1 previous error

View File

@@ -48,13 +48,6 @@ unsafe fn simd_flog10<T>(x: T) -> T;
#[rustc_intrinsic]
unsafe fn simd_flog2<T>(x: T) -> T;
#[rustc_intrinsic]
unsafe fn simd_fpow<T>(x: T, y: T) -> T;
#[rustc_intrinsic]
unsafe fn simd_fpowi<T>(x: T, y: i32) -> T;
// rounding functions
#[rustc_intrinsic]
unsafe fn simd_ceil<T>(x: T) -> T;
@@ -68,23 +61,21 @@ unsafe fn simd_round<T>(x: T) -> T;
#[rustc_intrinsic]
unsafe fn simd_trunc<T>(x: T) -> T;
macro_rules! assert_approx_eq_f32 {
($a:expr, $b:expr) => ({
($a:expr, $b:expr) => {{
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
})
assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
}};
}
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
($a:expr, $b:expr) => {{
let a = $a;
let b = $b;
assert_approx_eq_f32!(a.0[0], b.0[0]);
assert_approx_eq_f32!(a.0[1], b.0[1]);
assert_approx_eq_f32!(a.0[2], b.0[2]);
assert_approx_eq_f32!(a.0[3], b.0[3]);
})
}};
}
fn main() {
@@ -125,12 +116,6 @@ fn main() {
let r = simd_flog10(x);
assert_approx_eq!(z, r);
let r = simd_fpow(h, x);
assert_approx_eq!(h, r);
let r = simd_fpowi(h, 1);
assert_approx_eq!(h, r);
let r = simd_fsin(z);
assert_approx_eq!(z, r);

View File

@@ -0,0 +1,6 @@
error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
error: aborting due to 1 previous error

View File

@@ -1,7 +1,7 @@
// Regression test for #129541
//@ revisions: unique multiple
//@ check-pass
//@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
trait Bound {}
trait Normalize {

View File

@@ -0,0 +1,6 @@
error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
error: aborting due to 1 previous error

View File

@@ -1,5 +1,5 @@
//! This test checks that we currently need to implement
//! members, even if their where bounds don't hold for the impl type.
//! This test checks that we do not need to implement
//! members, whose `where Self: Sized` bounds don't hold for the impl type.
trait Foo {
fn foo()
@@ -15,12 +15,28 @@ impl Foo for () {
impl Foo for i32 {}
//~^ ERROR: not all trait items implemented, missing: `foo`
// Should be allowed
impl Foo for dyn std::fmt::Debug {}
//~^ ERROR: not all trait items implemented, missing: `foo`
#[deny(dead_code)]
impl Foo for dyn std::fmt::Display {
fn foo() {}
//~^ ERROR this item cannot be used as its where bounds are not satisfied
}
struct Struct {
i: i32,
tail: [u8],
}
impl Foo for Struct {}
// Ensure we only allow known-unsized types to be skipped
trait Trait {
fn foo(self)
where
Self: Sized;
}
impl<T: ?Sized> Trait for T {}
//~^ ERROR: not all trait items implemented, missing: `foo`
fn main() {}

View File

@@ -9,17 +9,29 @@ LL | | Self: Sized;
LL | impl Foo for i32 {}
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl_sized.rs:19:1
error: this item cannot be used as its where bounds are not satisfied for the `Self` type
--> $DIR/trivial_impl_sized.rs:22:5
|
LL | / fn foo()
LL | fn foo() {}
| ^^^^^^^^
|
note: the lint level is defined here
--> $DIR/trivial_impl_sized.rs:20:8
|
LL | #[deny(dead_code)]
| ^^^^^^^^^
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl_sized.rs:39:1
|
LL | / fn foo(self)
LL | | where
LL | | Self: Sized;
| |____________________- `foo` from trait
...
LL | impl Foo for dyn std::fmt::Debug {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
LL | }
LL | impl<T: ?Sized> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0046`.

View File

@@ -0,0 +1,7 @@
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Sample)]
pub fn sample(_: TokenStream) -> TokenStream {
"fn bad<T: Into<U>, U>(a: T) -> U { a }".parse().unwrap()
}

View File

@@ -0,0 +1,9 @@
//@ proc-macro: derive-demo-issue-136343.rs
#[macro_use]
extern crate derive_demo_issue_136343;
#[derive(Sample)] //~ ERROR mismatched types
struct Test;
fn main() {}

View File

@@ -0,0 +1,19 @@
error[E0308]: mismatched types
--> $DIR/invalid-sugg-for-derive-macro-issue-136343.rs:6:10
|
LL | #[derive(Sample)]
| ^^^^^^
| |
| expected type parameter `U`, found type parameter `T`
| expected `U` because of return type
|
= note: expected type parameter `U`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= note: the caller chooses a type for `U` which can be different from `T`
= note: this error originates in the derive macro `Sample` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.