diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 364a6a035ab8..bedc6ca11b3f 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -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"] } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 0929218ea2b2..dd6d8dbb6f5e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -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 diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 84cd5b002fbb..8b454ab2a424 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -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 diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 56fae135e552..1169b9c067d7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -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 diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index d9c5c3e5af96..bfa7635a869f 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -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`. diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4c0764502694..b090730ac6b5 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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"); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ceed0cd94fc9..f2b133f56773 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -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)] diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 6d16dc00ef4e..306535bf7642 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -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" ), // ========================================================================== diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6badd2909175..3f75cce00922 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -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 diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 09320b868783..f2331f3fd8e1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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)); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index fedc197e7efa..42d785c8dd0f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -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)) } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 99262f9871e0..852533ff5c95 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -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 { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index f9fc12159363..35a3491f7c08 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -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; } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index c1aa95667da6..23f037f3692a 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -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; +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 { + 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 { + 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; + + 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), } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ded50d98db5e..5c5b3b350dd4 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -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)] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index b817b4cb7b83..ebcc0efd5a67 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -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)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 93a7227d65ee..48ea7df5c23f 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -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)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index eb4ac6ce77c9..ea48d0cad745 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -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)] diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index a39bb884faad..141d261b5f01 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -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::(); // 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..], diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c09669d959c9..bca9323a50d4 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -31,6 +31,7 @@ #![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(slice_as_chunks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 172c2faca963..501c9039f2de 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1877,8 +1877,6 @@ symbols! { simd_fma, simd_fmax, simd_fmin, - simd_fpow, - simd_fpowi, simd_fsin, simd_fsqrt, simd_gather, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 761d2848a059..cc8162a2f27e 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -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"` // diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1af383e9200d..b235d0da83cc 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -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)] diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 51790b13ec77..46385ca3a6fd 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -131,8 +131,6 @@ pub struct TraitPredicate { /// 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, } diff --git a/library/Cargo.lock b/library/Cargo.lock index 0ad56f3ce47a..de9685742f59 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -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", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 6f9074d91b01..9e80f3579e80 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -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"] } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 6d305386dbfa..78b7da9d6b3e 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -289,7 +289,7 @@ impl Clone for BTreeMap { } } -/// Internal functionality for `BTreeSet`. +// Internal functionality for `BTreeSet`. impl BTreeMap { pub(super) fn replace(&mut self, key: K) -> Option where diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 13168b7a39fe..3183268b4b32 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1140,7 +1140,6 @@ impl LinkedList { /// Splitting a list into evens and odds, reusing the original list: /// /// ``` - /// #![feature(extract_if)] /// use std::collections::LinkedList; /// /// let mut numbers: LinkedList = LinkedList::new(); @@ -1152,7 +1151,7 @@ impl LinkedList { /// assert_eq!(evens.into_iter().collect::>(), vec![2, 4, 6, 8, 14]); /// assert_eq!(odds.into_iter().collect::>(), 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(&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 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 fmt::Debug for ExtractIf<'_, T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("ExtractIf").field(&self.list).finish() diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 9446afd4b24b..f10ef1fca137 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -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::::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 diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index 4db13981596b..be869553ef4e 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -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 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 Drop for ExtractIf<'_, T, F, A> { fn drop(&mut self) { unsafe { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a84bb724473a..701144cc3af2 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -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 [len] == [capacity], -/// (as is the case for the [`vec!`] macro), then a `Vec` 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 [len] == [capacity], then a `Vec` 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::\]: 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 Vec { /// 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::>(); @@ -3697,13 +3708,12 @@ impl Vec { /// 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::>(); /// 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(&mut self, range: R, filter: F) -> ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f95be6a6df0b..785070fb2bbc 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -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)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index edc39f8f28cf..786a5a5b6bba 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1041,7 +1041,6 @@ impl MaybeUninit { /// 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 MaybeUninit { /// 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 [MaybeUninit] { /// /// [`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, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d47af93c1601..7a2764206e8d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -956,7 +956,6 @@ impl [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] { #[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 diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index de68f80aa0c8..1276d9014f0e 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -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` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 064923edb41f..83ad10db2da4 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -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) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index a0a28e807960..f4d4894c1bbd 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -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', diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 93d254e34f5e..ff4a4b35ce45 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -656,7 +656,6 @@ impl HashMap { /// Splitting a map into even and odd keys, reusing the original map: /// /// ``` - /// #![feature(hash_extract_if)] /// use std::collections::HashMap; /// /// let mut map: HashMap = (0..8).map(|x| (x, x)).collect(); @@ -672,7 +671,7 @@ impl HashMap { /// ``` #[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(&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 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 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, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index c265d42d06a9..a547a9943c1a 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -293,7 +293,6 @@ impl HashSet { /// Splitting a set into even and odd values, reusing the original set: /// /// ``` - /// #![feature(hash_extract_if)] /// use std::collections::HashSet; /// /// let mut set: HashSet = (0..8).collect(); @@ -309,7 +308,7 @@ impl HashSet { /// ``` #[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(&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 fmt::Debug for Drain<'_, K> { } } -#[unstable(feature = "hash_extract_if", issue = "59618")] +#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] impl 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 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, diff --git a/library/std/src/sys/pal/zkvm/stdio.rs b/library/std/src/sys/pal/zkvm/stdio.rs index 5f1d06dd1d78..0bcb54744b0b 100644 --- a/library/std/src/sys/pal/zkvm/stdio.rs +++ b/library/std/src/sys/pal/zkvm/stdio.rs @@ -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 { 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 { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index a47f3af60cbd..890e64e2babb 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -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", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index ed51862390d4..2c1d85b01e6a 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -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" } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index ac971a64d7c2..e3f58d97cbc4 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -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::") diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index d335ce65ad53..02d6f205d802 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -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. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index d4b72ead045e..2be42f16e2ab 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -218,6 +218,8 @@ pub struct Config { pub stderr_is_tty: bool, pub on_fail: Option, + pub explicit_stage_from_cli: bool, + pub explicit_stage_from_config: bool, pub stage: u32, pub keep_stage: Vec, pub keep_stage_std: Vec, @@ -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()`. diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index f0a185ee3a7e..eff5e0337428 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -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()); +} diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 3ef9c7ac35e9..8f0b67ddbd36 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -154,7 +154,6 @@ pub fn get_closest_merge_commit( "rev-list", &format!("--author={}", config.git_merge_commit_email), "-n1", - "--first-parent", &merge_base, ]); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index a158e5b6253c..3428dd4826a7 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.20.2 \ No newline at end of file +0.20.3 \ No newline at end of file diff --git a/src/tools/cargo b/src/tools/cargo index ce948f4616e3..1d1d646c06a8 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ce948f4616e3d4277e30c75c8bb01e094910df39 +Subproject commit 1d1d646c06a84c1aa53967b394b7f1218f85db82 diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b3e207f53b8b..9ab3d5a6e7f5 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f5729cfed3c45e061e8a443677fc1d5ef9277df7 +cb06d12710575a0d7ff71d6fe108f3bcff4f9195 diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index b85e38eab2aa..85fb280a9a90 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -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)?; } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index abfa90b193ea..0bf5ae87f383 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -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, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index ee755e4c1826..505c079143a4 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -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)?; } diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index d8792a6c3026..05ac5e82b564 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -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 { diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs deleted file mode 100644 index 3527f71c00b4..000000000000 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ /dev/null @@ -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(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) -} diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs deleted file mode 100644 index 4f0b5e4e01a3..000000000000 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ /dev/null @@ -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(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) -} diff --git a/tests/run-make/include-all-symbols-linking/lib.rs b/tests/run-make/include-all-symbols-linking/lib.rs index 99508bcdaf31..73186ee99e3d 100644 --- a/tests/run-make/include-all-symbols-linking/lib.rs +++ b/tests/run-make/include-all-symbols-linking/lib.rs @@ -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]; } diff --git a/tests/run-make/include-all-symbols-linking/rmake.rs b/tests/run-make/include-all-symbols-linking/rmake.rs index 77fd71ab20d2..bab510fb5be3 100644 --- a/tests/run-make/include-all-symbols-linking/rmake.rs +++ b/tests/run-make/include-all-symbols-linking/rmake.rs @@ -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") diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml index c62683b45da9..b96f6ddcc37a 100644 --- a/tests/rustdoc-gui/code-example-buttons.goml +++ b/tests/rustdoc-gui/code-example-buttons.goml @@ -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", diff --git a/tests/rustdoc-gui/copy-path.goml b/tests/rustdoc-gui/copy-path.goml index dc05b96f7aed..e8766688f8d5 100644 --- a/tests/rustdoc-gui/copy-path.goml +++ b/tests/rustdoc-gui/copy-path.goml @@ -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. diff --git a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs new file mode 100644 index 000000000000..686dcb277f89 --- /dev/null +++ b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs @@ -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"); +} diff --git a/tests/ui/attributes/used_with_archive.rs b/tests/ui/attributes/used_with_archive.rs new file mode 100644 index 000000000000..ff29456b87d2 --- /dev/null +++ b/tests/ui/attributes/used_with_archive.rs @@ -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"); +} diff --git a/tests/ui/attributes/used_with_archive.run.stdout b/tests/ui/attributes/used_with_archive.run.stdout new file mode 100644 index 000000000000..212372b3e579 --- /dev/null +++ b/tests/ui/attributes/used_with_archive.run.stdout @@ -0,0 +1,2 @@ +constructor +main diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr index b0c493faf1ef..23341ec6bdc2 100644 --- a/tests/ui/did_you_mean/recursion_limit_deref.stderr +++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr @@ -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`. diff --git a/tests/ui/drop/lint-if-let-rescope-false-positives.rs b/tests/ui/drop/lint-if-let-rescope-false-positives.rs new file mode 100644 index 000000000000..77b7df4bc3ba --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-false-positives.rs @@ -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 { + Some(1) + } +} + +fn consume(_: impl Sized) -> Option { 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 {} +} diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 182190aa323b..79858e6f225a 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -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] diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index e1b38be0a0f5..9d873c65426f 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -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] diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 2b0fcb7a938a..b17239976cc0 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -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 +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 diff --git a/tests/ui/force-inlining/gate.rs b/tests/ui/force-inlining/gate.rs index d6a01a74a44b..cea094c14f2d 100644 --- a/tests/ui/force-inlining/gate.rs +++ b/tests/ui/force-inlining/gate.rs @@ -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() { } diff --git a/tests/ui/force-inlining/gate.stderr b/tests/ui/force-inlining/gate.stderr index e3973a08c232..964d43fa18f6 100644 --- a/tests/ui/force-inlining/gate.stderr +++ b/tests/ui/force-inlining/gate.stderr @@ -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"] diff --git a/tests/ui/invalid/issue-114435-layout-type-err.rs b/tests/ui/invalid/issue-114435-layout-type-err.rs index f68744a13c15..2a86839e416f 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.rs +++ b/tests/ui/invalid/issue-114435-layout-type-err.rs @@ -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() {} diff --git a/tests/ui/invalid/issue-114435-layout-type-err.stderr b/tests/ui/invalid/issue-114435-layout-type-err.stderr index a2db74ff8bd8..2fddc62f004f 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.stderr +++ b/tests/ui/invalid/issue-114435-layout-type-err.stderr @@ -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 diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index 74cb51a06068..91059f353fd9 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -48,13 +48,6 @@ unsafe fn simd_flog10(x: T) -> T; #[rustc_intrinsic] unsafe fn simd_flog2(x: T) -> T; -#[rustc_intrinsic] -unsafe fn simd_fpow(x: T, y: T) -> T; - -#[rustc_intrinsic] -unsafe fn simd_fpowi(x: T, y: i32) -> T; - - // rounding functions #[rustc_intrinsic] unsafe fn simd_ceil(x: T) -> T; @@ -68,23 +61,21 @@ unsafe fn simd_round(x: T) -> T; #[rustc_intrinsic] unsafe fn simd_trunc(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); diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr new file mode 100644 index 000000000000..93b064cdce2a --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr @@ -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 + diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index 4fbcbefec913..729771e560e9 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -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 { diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr new file mode 100644 index 000000000000..93b064cdce2a --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr @@ -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 + diff --git a/tests/ui/traits/trivial_impl_sized.rs b/tests/ui/traits/trivial_impl_sized.rs index 501a3405090e..59cc079c2682 100644 --- a/tests/ui/traits/trivial_impl_sized.rs +++ b/tests/ui/traits/trivial_impl_sized.rs @@ -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 Trait for T {} +//~^ ERROR: not all trait items implemented, missing: `foo` + fn main() {} diff --git a/tests/ui/traits/trivial_impl_sized.stderr b/tests/ui/traits/trivial_impl_sized.stderr index ebf6dfc9dd2d..95cab3371826 100644 --- a/tests/ui/traits/trivial_impl_sized.stderr +++ b/tests/ui/traits/trivial_impl_sized.stderr @@ -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 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`. diff --git a/tests/ui/typeck/auxiliary/derive-demo-issue-136343.rs b/tests/ui/typeck/auxiliary/derive-demo-issue-136343.rs new file mode 100644 index 000000000000..65be439b49a9 --- /dev/null +++ b/tests/ui/typeck/auxiliary/derive-demo-issue-136343.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Sample)] +pub fn sample(_: TokenStream) -> TokenStream { + "fn bad, U>(a: T) -> U { a }".parse().unwrap() +} diff --git a/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.rs b/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.rs new file mode 100644 index 000000000000..c08030fc5c15 --- /dev/null +++ b/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.rs @@ -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() {} diff --git a/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.stderr b/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.stderr new file mode 100644 index 000000000000..0b9c1d9123aa --- /dev/null +++ b/tests/ui/typeck/invalid-sugg-for-derive-macro-issue-136343.stderr @@ -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`.