diff options
108 files changed, 1334 insertions, 622 deletions
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index c48920e5f1b..0bc1c8a0930 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -12,66 +12,93 @@ use crate::AbiFromStrErr; #[cfg(test)] mod tests; -use ExternAbi as Abi; - +/// ABI we expect to see within `extern "{abi}"` #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable))] pub enum ExternAbi { - // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the - // hashing tests. These are used in many places, so giving them stable values reduces test - // churn. The specific values are meaningless. - Rust, + /* universal */ + /// presumed C ABI for the platform C { unwind: bool, }, - Cdecl { + /// ABI of the "system" interface, e.g. the Win32 API, always "aliasing" + System { unwind: bool, }, - Stdcall { + + /// that's us! + Rust, + /// the mostly-unused `unboxed_closures` ABI, effectively now an impl detail unless someone + /// puts in the work to make it viable again... but would we need a special ABI? + RustCall, + /// For things unlikely to be called, where reducing register pressure in + /// `extern "Rust"` callers is worth paying extra cost in the callee. + /// Stronger than just `#[cold]` because `fn` pointers might be incompatible. + RustCold, + + /// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM. + /// Even normally-compatible Rust types can become ABI-incompatible with this ABI! + Unadjusted, + + /// UEFI ABI, usually an alias of C, but sometimes an arch-specific alias + /// and only valid on platforms that have a UEFI standard + EfiApi, + + /* arm */ + /// Arm Architecture Procedure Call Standard, sometimes `ExternAbi::C` is an alias for this + Aapcs { unwind: bool, }, - Fastcall { + /// extremely constrained barely-C ABI for TrustZone + CCmseNonSecureCall, + /// extremely constrained barely-C ABI for TrustZone + CCmseNonSecureEntry, + + /* gpu */ + /// An entry-point function called by the GPU's host + // FIXME: should not be callable from Rust on GPU targets, is for host's use only + GpuKernel, + /// An entry-point function called by the GPU's host + // FIXME: why do we have two of these? + PtxKernel, + + /* interrupt */ + AvrInterrupt, + AvrNonBlockingInterrupt, + Msp430Interrupt, + RiscvInterruptM, + RiscvInterruptS, + X86Interrupt, + + /* x86 */ + /// `ExternAbi::C` but spelled funny because x86 + Cdecl { unwind: bool, }, - Vectorcall { + /// gnu-stdcall on "unix" and win-stdcall on "windows" + Stdcall { unwind: bool, }, - Thiscall { + /// gnu-fastcall on "unix" and win-fastcall on "windows" + Fastcall { unwind: bool, }, - Aapcs { + /// windows C++ ABI + Thiscall { unwind: bool, }, - Win64 { + /// uses AVX and stuff + Vectorcall { unwind: bool, }, + + /* x86_64 */ SysV64 { unwind: bool, }, - PtxKernel, - Msp430Interrupt, - X86Interrupt, - /// An entry-point function called by the GPU's host - // FIXME: should not be callable from Rust on GPU targets, is for host's use only - GpuKernel, - EfiApi, - AvrInterrupt, - AvrNonBlockingInterrupt, - CCmseNonSecureCall, - CCmseNonSecureEntry, - System { + Win64 { unwind: bool, }, - RustCall, - /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even - /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! - Unadjusted, - /// For things unlikely to be called, where reducing register pressure in - /// `extern "Rust"` callers is worth paying extra cost in the callee. - /// Stronger than just `#[cold]` because `fn` pointers might be incompatible. - RustCold, - RiscvInterruptM, - RiscvInterruptS, } macro_rules! abi_impls { @@ -224,7 +251,7 @@ pub fn all_names() -> Vec<&'static str> { impl ExternAbi { /// Default ABI chosen for `extern fn` declarations without an explicit ABI. - pub const FALLBACK: Abi = Abi::C { unwind: false }; + pub const FALLBACK: ExternAbi = ExternAbi::C { unwind: false }; pub fn name(self) -> &'static str { self.as_str() diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs index 69ce17d3d75..704f866e2c4 100644 --- a/compiler/rustc_codegen_cranelift/example/neon.rs +++ b/compiler/rustc_codegen_cranelift/example/neon.rs @@ -233,7 +233,7 @@ unsafe fn test_vaddvq_f32() { #[cfg(target_arch = "aarch64")] unsafe fn test_vrndnq_f32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.frintn.v4f32 + // llvm intrinsic: llvm.roundeven.v4f32 let a = f32x4::from([0.1, -1.9, 4.5, 5.5]); let e = f32x4::from([0., -2., 4., 6.]); let r: f32x4 = transmute(vrndnq_f32(transmute(a))); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index 99a5518d0b6..2dee9176936 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -62,6 +62,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }); } + _ if intrinsic.starts_with("llvm.roundeven.v") => { + intrinsic_args!(fx, args => (v); intrinsic); + + simd_for_each_lane(fx, v, ret, &|fx, _lane_ty, _res_lane_ty, lane| { + fx.bcx.ins().nearest(lane) + }); + } + _ => { fx.tcx .dcx() diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs index c22f2a7b873..3cd7ebb88f4 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs @@ -264,14 +264,6 @@ pub(super) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().fadd(a, b)); } - _ if intrinsic.starts_with("llvm.aarch64.neon.frintn.v") => { - intrinsic_args!(fx, args => (v); intrinsic); - - simd_for_each_lane(fx, v, ret, &|fx, _lane_ty, _res_lane_ty, lane| { - fx.bcx.ins().nearest(lane) - }); - } - _ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => { intrinsic_args!(fx, args => (v); intrinsic); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index bd421a441f9..6f0090a0bd6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1529,7 +1529,7 @@ impl DiagCtxtInner { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and // stashed below, so they'll trigger the must_produce_diag check. - assert_matches!(diagnostic.level, Error | Warning | Allow | Expect); + assert_matches!(diagnostic.level, Error | ForceWarning | Warning | Allow | Expect); self.future_breakage_diagnostics.push(diagnostic.clone()); } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f255817bffc..a92ee89186c 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -192,10 +192,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); }); - // Make sure we evaluate all static and (non-associated) const items, even if unused. - // If any of these fail to evaluate, we do not want this crate to pass compilation. tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); + // Make sure we evaluate all static and (non-associated) const items, even if unused. + // If any of these fail to evaluate, we do not want this crate to pass compilation. match def_kind { DefKind::Static { .. } => { tcx.ensure_ok().eval_static_initializer(item_def_id); @@ -215,6 +215,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) { if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); } + // Ensure we generate the new `DefId` before finishing `check_crate`. + // Afterwards we freeze the list of `DefId`s. + if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) { + tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id); + } }); if tcx.features().rustc_attrs() { diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index e144a6ab599..e17cfc15a43 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -380,20 +380,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_label(self.span, "invalid cast"); if self.expr_ty.is_numeric() { if self.expr_ty == fcx.tcx.types.u32 { - match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { - Ok(snippet) => err.span_suggestion( - self.span, - "try `char::from_u32` instead", - format!("char::from_u32({snippet})"), - Applicability::MachineApplicable, - ), - - Err(_) => err.span_help(self.span, "try `char::from_u32` instead"), - }; + err.multipart_suggestion( + "consider using `char::from_u32` instead", + vec![ + (self.expr_span.shrink_to_lo(), "char::from_u32(".to_string()), + (self.expr_span.shrink_to_hi().to(self.cast_span), ")".to_string()), + ], + Applicability::MachineApplicable, + ); } else if self.expr_ty == fcx.tcx.types.i8 { - err.span_help(self.span, "try casting from `u8` instead"); + err.span_help(self.span, "consider casting from `u8` instead"); } else { - err.span_help(self.span, "try `char::from_u32` instead (via a `u32`)"); + err.span_help( + self.span, + "consider using `char::from_u32` instead (via a `u32`)", + ); }; } err.emit(); @@ -494,11 +495,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.cast_ty.kind(), ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) ) { - let mut label = true; // Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion: - if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) - && let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) - { + if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) { let ty = fcx.resolve_vars_if_possible(self.cast_ty); let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); if fcx @@ -506,26 +504,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { .type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env) .must_apply_modulo_regions() { - label = false; - if let ty::Adt(def, args) = self.cast_ty.kind() { - err.span_suggestion_verbose( - self.span, - "consider using the `From` trait instead", - format!( - "{}::from({})", - fcx.tcx.value_path_str_with_args(def.did(), args), - snippet - ), - Applicability::MaybeIncorrect, - ); + let to_ty = if let ty::Adt(def, args) = self.cast_ty.kind() { + fcx.tcx.value_path_str_with_args(def.did(), args) } else { - err.span_suggestion( - self.span, - "consider using the `From` trait instead", - format!("{}::from({})", self.cast_ty, snippet), - Applicability::MaybeIncorrect, - ); + self.cast_ty.to_string() }; + err.multipart_suggestion( + "consider using the `From` trait instead", + vec![ + (self.expr_span.shrink_to_lo(), format!("{to_ty}::from(")), + ( + self.expr_span.shrink_to_hi().to(self.cast_span), + ")".to_string(), + ), + ], + Applicability::MaybeIncorrect, + ); } } @@ -548,11 +542,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) }; - if label { - err.span_label(self.span, msg); - } else { - err.note(msg); - } + err.span_label(self.span, msg); if let Some(note) = note { err.note(note); @@ -654,38 +644,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { match self.expr_ty.kind() { ty::Ref(_, _, mt) => { let mtstr = mt.prefix_str(); - match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { - Ok(s) => { - err.span_suggestion( - self.cast_span, - "try casting to a reference instead", - format!("&{mtstr}{s}"), - Applicability::MachineApplicable, - ); - } - Err(_) => { - let msg = format!("did you mean `&{mtstr}{tstr}`?"); - err.span_help(self.cast_span, msg); - } - } + err.span_suggestion_verbose( + self.cast_span.shrink_to_lo(), + "consider casting to a reference instead", + format!("&{mtstr}"), + Applicability::MachineApplicable, + ); } ty::Adt(def, ..) if def.is_box() => { - match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { - Ok(s) => { - err.span_suggestion( - self.cast_span, - "you can cast to a `Box` instead", - format!("Box<{s}>"), - Applicability::MachineApplicable, - ); - } - Err(_) => { - err.span_help( - self.cast_span, - format!("you might have meant `Box<{tstr}>`"), - ); - } - } + err.multipart_suggestion( + "you can cast to a `Box` instead", + vec![ + (self.cast_span.shrink_to_lo(), "Box<".to_string()), + (self.cast_span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); } _ => { err.span_help(self.expr_span, "consider using a box or reference as appropriate"); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 96e03e3bea5..e9b58eb959b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -823,6 +823,13 @@ impl<'tcx> InferCtxt<'tcx> { ty::Region::new_var(self.tcx, region_var) } + pub fn next_term_var_of_kind(&self, term: ty::Term<'tcx>, span: Span) -> ty::Term<'tcx> { + match term.kind() { + ty::TermKind::Ty(_) => self.next_ty_var(span).into(), + ty::TermKind::Const(_) => self.next_const_var(span).into(), + } + } + /// Return the universe that the region `r` was created in. For /// most regions (e.g., `'static`, named regions from the user, /// etc) this is the root universe U0. For inference variables or diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ee41df6b1f6..2643e5c1926 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -976,13 +976,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { }); rustc_hir_analysis::check_crate(tcx); - sess.time("MIR_coroutine_by_move_body", || { - tcx.par_hir_body_owners(|def_id| { - if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { - tcx.ensure_done().coroutine_by_move_body_def_id(def_id); - } - }); - }); // Freeze definitions as we don't add new ones at this point. // We need to wait until now since we synthesize a by-move body // for all coroutine-closures. diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index 5de2cbf9939..845a1f1b81f 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -16,7 +16,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,compile_fail /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] { /// unsafe { &raw mut (*ptr)[..16] } /// // ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`, @@ -51,7 +51,7 @@ declare_lint! { /// } /// ``` pub DANGEROUS_IMPLICIT_AUTOREFS, - Warn, + Deny, "implicit reference to a dereference of a raw pointer", report_in_external_macro } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index cb3fdd4d3f7..7135b8f04a2 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -51,6 +51,7 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(ptr_alignment_type)] +#![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(trusted_len)] diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 7243f87ee63..47ba850d50d 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::fmt; use std::hash::Hash; @@ -468,6 +469,29 @@ impl<'tcx> CodegenUnit<'tcx> { hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE) } + pub fn shorten_name(human_readable_name: &str) -> Cow<'_, str> { + // Set a limit a somewhat below the common platform limits for file names. + const MAX_CGU_NAME_LENGTH: usize = 200; + const TRUNCATED_NAME_PREFIX: &str = "-trunc-"; + if human_readable_name.len() > MAX_CGU_NAME_LENGTH { + let mangled_name = Self::mangle_name(human_readable_name); + // Determine a safe byte offset to truncate the name to + let truncate_to = human_readable_name.floor_char_boundary( + MAX_CGU_NAME_LENGTH - TRUNCATED_NAME_PREFIX.len() - mangled_name.len(), + ); + format!( + "{}{}{}", + &human_readable_name[..truncate_to], + TRUNCATED_NAME_PREFIX, + mangled_name + ) + .into() + } else { + // If the name is short enough, we can just return it as is. + human_readable_name.into() + } + } + pub fn compute_size_estimate(&mut self) { // The size of a codegen unit as the sum of the sizes of the items // within it. @@ -604,7 +628,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> { let cgu_name = self.build_cgu_name_no_mangle(cnum, components, special_suffix); if self.tcx.sess.opts.unstable_opts.human_readable_cgu_names { - cgu_name + Symbol::intern(&CodegenUnit::shorten_name(cgu_name.as_str())) } else { Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str())) } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index b4169a060d4..49025673bbd 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -461,15 +461,15 @@ fn merge_codegen_units<'tcx>( for cgu in codegen_units.iter_mut() { if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) { - if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names { - cgu.set_name(Symbol::intern(new_cgu_name)); + let new_cgu_name = if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names { + Symbol::intern(&CodegenUnit::shorten_name(new_cgu_name)) } else { // If we don't require CGU names to be human-readable, // we use a fixed length hash of the composite CGU name // instead. - let new_cgu_name = CodegenUnit::mangle_name(new_cgu_name); - cgu.set_name(Symbol::intern(&new_cgu_name)); - } + Symbol::intern(&CodegenUnit::mangle_name(new_cgu_name)) + }; + cgu.set_name(new_cgu_name); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5b7d45bb152..dc29b03083f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1266,13 +1266,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { true } - /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if - /// valid. - fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) { + /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place. + fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) { if let Some(metas) = meta.meta_item_list() { for i_meta in metas { match (i_meta.name(), i_meta.meta_item()) { - (Some(sym::attr | sym::no_crate_inject), _) => {} + (Some(sym::attr), _) => { + // Allowed everywhere like `#[doc]` + } + (Some(sym::no_crate_inject), _) => { + self.check_attr_crate_level(attr, meta, hir_id); + } (_, Some(m)) => { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, @@ -1359,9 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } Some(sym::test) => { - if self.check_attr_crate_level(attr, meta, hir_id) { - self.check_test_attr(meta, hir_id); - } + self.check_test_attr(attr, meta, hir_id); } Some( diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 46fcd7d5c51..aa6d1ec7009 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -124,7 +124,13 @@ pub(crate) fn base( // to v4, so we do the same. // https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203 default_dwarf_version: 4, - frame_pointer: FramePointer::Always, + frame_pointer: match arch { + // clang ignores `-fomit-frame-pointer` for Armv7, it only accepts `-momit-leaf-frame-pointer` + Armv7k | Armv7s => FramePointer::Always, + // clang supports omitting frame pointers for the rest, but... don't? + Arm64 | Arm64e | Arm64_32 => FramePointer::NonLeaf, + I386 | I686 | X86_64 | X86_64h => FramePointer::Always, + }, has_rpath: true, dll_suffix: ".dylib".into(), archive_format: "darwin".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 6587abb2ba7..4dd39877715 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal); @@ -17,7 +17,6 @@ pub(crate) fn target() -> Target { arch, options: TargetOptions { mcount: "\u{1}mcount".into(), - frame_pointer: FramePointer::NonLeaf, cpu: "apple-m1".into(), max_atomic_width: Some(128), // FIXME: The leak sanitizer currently fails the tests, see #88132. diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 183a6c6f2d7..769a7b6c391 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index ce9ae03e699..4bb2f73e4f9 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 4405e3fec02..7d04034e759 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index 037685db1b3..ec92a40e255 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions}; +use crate::spec::{Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index a386220e6fc..74fbe5a89ca 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions}; +use crate::spec::{Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index 2c1dfdd55ed..dc595fbe7b6 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index c0b8b409797..06ff1bfb2f0 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index 62968f5b555..bad9f6c1485 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions}; +use crate::spec::{Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs index 79b95dbde52..326f2b16d59 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal); @@ -17,7 +17,6 @@ pub(crate) fn target() -> Target { arch, options: TargetOptions { mcount: "\u{1}mcount".into(), - frame_pointer: FramePointer::NonLeaf, cpu: "apple-m1".into(), max_atomic_width: Some(128), // FIXME: The leak sanitizer currently fails the tests, see #88132. diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index 848dbeec199..01c6f0b888d 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, ..opts }, diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs index 3dbe169e826..cad3650bda1 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions}; +use crate::spec::{Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), max_atomic_width: Some(128), - frame_pointer: FramePointer::NonLeaf, ..opts }, } diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 161db9a08bb..d1339c57b00 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions}; +use crate::spec::{Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); @@ -16,11 +16,6 @@ pub(crate) fn target() -> Target { i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), arch, - options: TargetOptions { - mcount: "\u{1}mcount".into(), - max_atomic_width: Some(64), - frame_pointer: FramePointer::Always, - ..opts - }, + options: TargetOptions { mcount: "\u{1}mcount".into(), max_atomic_width: Some(64), ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 64c17054780..eba595ba7dd 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,5 +1,5 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); @@ -18,7 +18,6 @@ pub(crate) fn target() -> Target { options: TargetOptions { mcount: "\u{1}mcount".into(), max_atomic_width: Some(128), // penryn+ supports cmpxchg16b - frame_pointer: FramePointer::Always, supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 11010b7d92f..e64556c4132 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,10 +1,9 @@ use crate::spec::base::apple::{Arch, TargetAbi, base}; -use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions}; +use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions}; pub(crate) fn target() -> Target { let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal); opts.max_atomic_width = Some(128); - opts.frame_pointer = FramePointer::Always; opts.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 3b7fd8b7a20..68bd9440538 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1411,7 +1411,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - err.span_suggestion( + err.span_suggestion_verbose( obligation.cause.span.shrink_to_lo(), format!( "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`" @@ -1574,7 +1574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .span_extend_while_whitespace(expr_span) .shrink_to_hi() .to(await_expr.span.shrink_to_hi()); - err.span_suggestion( + err.span_suggestion_verbose( removal_span, "remove the `.await`", "", @@ -2126,7 +2126,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )); if !assoc_item.is_impl_trait_in_trait() { - err.span_suggestion( + err.span_suggestion_verbose( span, "use the fully qualified path to an implementation", format!( @@ -2924,12 +2924,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); let sm = tcx.sess.source_map(); if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor) - && let Ok(snip) = sm.span_to_snippet(elt_span) + && let Ok(_) = sm.span_to_snippet(elt_span) { - err.span_suggestion( - elt_span, + err.multipart_suggestion( "create an inline `const` block", - format!("const {{ {snip} }}"), + vec![ + (elt_span.shrink_to_lo(), "const { ".to_string()), + (elt_span.shrink_to_hi(), " }".to_string()), + ], Applicability::MachineApplicable, ); } else { @@ -3127,13 +3129,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.help("change the field's type to have a statically known size"); - err.span_suggestion( + err.span_suggestion_verbose( span.shrink_to_lo(), "borrowed types always have a statically known size", "&", Applicability::MachineApplicable, ); - err.multipart_suggestion( + err.multipart_suggestion_verbose( "the `Box` type always has a statically known size and allocates its contents \ in the heap", vec![ diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1193a9059ca..d5d318ee490 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -133,45 +133,25 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { /// Instantiate the nested goals for the candidate without rolling back their /// inference constraints. This function modifies the state of the `infcx`. /// - /// See [`Self::instantiate_nested_goals_and_opt_impl_args`] if you need the impl args too. - pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> { - self.instantiate_nested_goals_and_opt_impl_args(span).0 - } - - /// Instantiate the nested goals for the candidate without rolling back their - /// inference constraints, and optionally the args of an impl if this candidate - /// came from a `CandidateSource::Impl`. This function modifies the state of the - /// `infcx`. + /// See [`Self::instantiate_impl_args`] if you need the impl args too. #[instrument( level = "debug", skip_all, fields(goal = ?self.goal.goal, steps = ?self.steps) )] - pub fn instantiate_nested_goals_and_opt_impl_args( - &self, - span: Span, - ) -> (Vec<InspectGoal<'a, 'tcx>>, Option<ty::GenericArgsRef<'tcx>>) { + pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> { let infcx = self.goal.infcx; let param_env = self.goal.goal.param_env; let mut orig_values = self.goal.orig_values.to_vec(); let mut instantiated_goals = vec![]; - let mut opt_impl_args = None; for step in &self.steps { match **step { inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push(( source, instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal), )), - inspect::ProbeStep::RecordImplArgs { impl_args } => { - opt_impl_args = Some(instantiate_canonical_state( - infcx, - span, - param_env, - &mut orig_values, - impl_args, - )); - } + inspect::ProbeStep::RecordImplArgs { .. } => {} inspect::ProbeStep::MakeCanonicalResponse { .. } | inspect::ProbeStep::NestedProbe(_) => unreachable!(), } @@ -187,14 +167,59 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let _ = term_hack.constrain(infcx, span, param_env); } - let opt_impl_args = opt_impl_args.map(|impl_args| eager_resolve_vars(infcx, impl_args)); - - let goals = instantiated_goals + instantiated_goals .into_iter() .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span)) - .collect(); + .collect() + } + + /// Instantiate the args of an impl if this candidate came from a + /// `CandidateSource::Impl`. This function modifies the state of the + /// `infcx`. + #[instrument( + level = "debug", + skip_all, + fields(goal = ?self.goal.goal, steps = ?self.steps) + )] + pub fn instantiate_impl_args(&self, span: Span) -> ty::GenericArgsRef<'tcx> { + let infcx = self.goal.infcx; + let param_env = self.goal.goal.param_env; + let mut orig_values = self.goal.orig_values.to_vec(); + + for step in &self.steps { + match **step { + inspect::ProbeStep::RecordImplArgs { impl_args } => { + let impl_args = instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + impl_args, + ); + + let () = instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + self.final_state, + ); + + // No reason we couldn't support this, but we don't need to for select. + assert!( + self.goal.normalizes_to_term_hack.is_none(), + "cannot use `instantiate_impl_args` with a `NormalizesTo` goal" + ); + + return eager_resolve_vars(infcx, impl_args); + } + inspect::ProbeStep::AddGoal(..) => {} + inspect::ProbeStep::MakeCanonicalResponse { .. } + | inspect::ProbeStep::NestedProbe(_) => unreachable!(), + } + } - (goals, opt_impl_args) + bug!("expected impl args probe step for `instantiate_impl_args`"); } pub fn instantiate_proof_tree_for_nested_goal( @@ -206,10 +231,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let infcx = self.goal.infcx; match goal.predicate.kind().no_bound_vars() { Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.kind() { - ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(_) => infcx.next_const_var(span).into(), - }; + let unconstrained_term = infcx.next_term_var_of_kind(term, span); let goal = goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index d903f94b489..8f44c26b70d 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,4 +1,3 @@ -use std::assert_matches::assert_matches; use std::fmt::Debug; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -16,7 +15,6 @@ use tracing::instrument; use super::{FulfillmentCtxt, NextSolverError}; use crate::error_reporting::InferCtxtErrorExt; use crate::error_reporting::traits::OverflowCause; -use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError}; /// Deeply normalize all aliases in `value`. This does not handle inference and expects @@ -97,19 +95,18 @@ impl<'tcx, E> NormalizationFolder<'_, 'tcx, E> where E: FromSolverError<'tcx, NextSolverError<'tcx>>, { - fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> { - assert_matches!(alias_ty.kind(), ty::Alias(..)); - + fn normalize_alias_term( + &mut self, + alias_term: ty::Term<'tcx>, + ) -> Result<ty::Term<'tcx>, Vec<E>> { let infcx = self.at.infcx; let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { - let ty::Alias(_, data) = *alias_ty.kind() else { - unreachable!(); - }; + let term = alias_term.to_alias_term().unwrap(); self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data.into()), + OverflowCause::DeeplyNormalize(term), self.at.cause.span, true, |_| {}, @@ -118,14 +115,14 @@ where self.depth += 1; - let new_infer_ty = infcx.next_ty_var(self.at.cause.span); + let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span); let obligation = Obligation::new( tcx, self.at.cause.clone(), self.at.param_env, ty::PredicateKind::AliasRelate( - alias_ty.into(), - new_infer_ty.into(), + alias_term.into(), + infer_term.into(), ty::AliasRelationDirection::Equate, ), ); @@ -135,50 +132,13 @@ where // Alias is guaranteed to be fully structurally resolved, // so we can super fold here. - let ty = infcx.resolve_vars_if_possible(new_infer_ty); - let result = ty.try_super_fold_with(self)?; - self.depth -= 1; - Ok(result) - } - - fn normalize_unevaluated_const( - &mut self, - uv: ty::UnevaluatedConst<'tcx>, - ) -> Result<ty::Const<'tcx>, Vec<E>> { - let infcx = self.at.infcx; - let tcx = infcx.tcx; - let recursion_limit = tcx.recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) { - self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(uv.into()), - self.at.cause.span, - true, - |_| {}, - ); - } - - self.depth += 1; - - let new_infer_ct = infcx.next_const_var(self.at.cause.span); - let obligation = Obligation::new( - tcx, - self.at.cause.clone(), - self.at.param_env, - ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() }, - ); - - let result = if infcx.predicate_may_hold(&obligation) { - self.fulfill_cx.register_predicate_obligation(infcx, obligation); - let errors = self.fulfill_cx.select_where_possible(infcx); - if !errors.is_empty() { - return Err(errors); - } - let ct = infcx.resolve_vars_if_possible(new_infer_ct); - ct.try_fold_with(self)? - } else { - ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)? + let term = infcx.resolve_vars_if_possible(infer_term); + // super-folding the `term` will directly fold the `Ty` or `Const` so + // we have to match on the term and super-fold them manually. + let result = match term.kind() { + ty::TermKind::Ty(ty) => ty.try_super_fold_with(self)?.into(), + ty::TermKind::Const(ct) => ct.try_super_fold_with(self)?.into(), }; - self.depth -= 1; Ok(result) } @@ -238,7 +198,8 @@ where if ty.has_escaping_bound_vars() { let (ty, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty); - let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?; + let result = + ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type(); Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -248,7 +209,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_alias_ty(ty)) + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type()) } } @@ -260,15 +221,13 @@ where return Ok(ct); } - let uv = match ct.kind() { - ty::ConstKind::Unevaluated(ct) => ct, - _ => return ct.try_super_fold_with(self), - }; + let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) }; - if uv.has_escaping_bound_vars() { - let (uv, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv); - let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?; + if ct.has_escaping_bound_vars() { + let (ct, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct); + let result = + ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const(); Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -278,7 +237,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv)) + Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const()) } } } diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 21812c8017d..fb1adc2fd2a 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -10,6 +10,7 @@ use rustc_infer::traits::{ use rustc_macros::extension; use rustc_middle::{bug, span_bug}; use rustc_span::Span; +use thin_vec::thin_vec; use crate::solve::inspect::{self, ProofTreeInferCtxtExt}; @@ -146,18 +147,21 @@ fn to_selection<'tcx>( return None; } - let (nested, impl_args) = cand.instantiate_nested_goals_and_opt_impl_args(span); - let nested = nested - .into_iter() - .map(|nested| { - Obligation::new( - nested.infcx().tcx, - ObligationCause::dummy_with_span(span), - nested.goal().param_env, - nested.goal().predicate, - ) - }) - .collect(); + let nested = match cand.result().expect("expected positive result") { + Certainty::Yes => thin_vec![], + Certainty::Maybe(_) => cand + .instantiate_nested_goals(span) + .into_iter() + .map(|nested| { + Obligation::new( + nested.infcx().tcx, + ObligationCause::dummy_with_span(span), + nested.goal().param_env, + nested.goal().predicate, + ) + }) + .collect(), + }; Some(match cand.kind() { ProbeKind::TraitCandidate { source, result: _ } => match source { @@ -166,7 +170,7 @@ fn to_selection<'tcx>( // For impl candidates, we do the rematch manually to compute the args. ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, - args: impl_args.expect("expected recorded impl args for impl candidate"), + args: cand.instantiate_impl_args(span), nested, }) } diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 3f741345404..2e20ede2f50 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -39,10 +39,7 @@ impl<'tcx> At<'_, 'tcx> { return Ok(term); } - let new_infer = match term.kind() { - ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(), - ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(), - }; + let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span); // We simply emit an `alias-eq` goal here, since that will take care of // normalizing the LHS of the projection until it is a rigid projection diff --git a/library/core/src/iter/sources/generator.rs b/library/core/src/iter/sources/generator.rs index c94232e09eb..155fa9368ad 100644 --- a/library/core/src/iter/sources/generator.rs +++ b/library/core/src/iter/sources/generator.rs @@ -9,8 +9,6 @@ /// /// ``` /// #![feature(iter_macro, coroutines)] -/// # #[cfg(not(bootstrap))] -/// # { /// /// let it = std::iter::iter!{|| { /// yield 1; @@ -19,7 +17,6 @@ /// } }(); /// let v: Vec<_> = it.collect(); /// assert_eq!(v, [1, 2, 3]); -/// # } /// ``` #[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")] #[allow_internal_unstable(coroutines, iter_from_coroutine)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 675556b07a8..c04754848b4 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -137,7 +137,7 @@ //! | [`ptr::NonNull<U>`] | when `U: Sized` | //! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type | //! -//! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`) +//! [^extern_fn]: this remains true for `unsafe` variants, any argument/return types, and any other ABI: `[unsafe] extern "abi" fn` (_e.g._, `extern "system" fn`) //! //! Under some conditions the above types `T` are also null pointer optimized when wrapped in a [`Result`][result_repr]. //! diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 91befdb8c78..d91f8bba548 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -52,7 +52,7 @@ impl [u8] { /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporaries. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] + #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 06161cb6c7c..41834793d22 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2671,7 +2671,7 @@ impl str { /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] + #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 21d5b7292e8..3cc225004ea 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -568,7 +568,7 @@ impl OsString { /// However, keep in mind that trimming the capacity may result in a reallocation and copy. /// /// [`into_boxed_os_str`]: Self::into_boxed_os_str - #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")] + #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn leak<'a>(self) -> &'a mut OsStr { OsStr::from_inner_mut(self.inner.leak()) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 014b56d28f4..826d9f0f39d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1252,7 +1252,7 @@ impl PathBuf { /// However, keep in mind that trimming the capacity may result in a reallocation and copy. /// /// [`into_boxed_path`]: Self::into_boxed_path - #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")] + #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn leak<'a>(self) -> &'a mut Path { Path::from_inner_mut(self.inner.leak()) diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index 781855a2d14..be0dda1d426 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -3,7 +3,6 @@ path_add_extension, path_file_prefix, maybe_uninit_slice, - os_string_pathbuf_leak, normalize_lexically )] diff --git a/library/stdarch b/library/stdarch -Subproject b6e2249e388f520627544812649b77b0944e1a2 +Subproject 5c1c436524c0bbc8db83577f42f8bea9006a7b7 diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 21a119e331e..9861637d8c8 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1313,10 +1313,8 @@ impl Builder<'_> { // // Notably this munges the dynamic library lookup path to point to the // right location to run `compiler`. - let mut lib_paths: Vec<PathBuf> = vec![ - self.build.rustc_snapshot_libdir(), - self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps"), - ]; + let mut lib_paths: Vec<PathBuf> = + vec![self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps")]; // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make // mode) and that C compiler may need some extra PATH modification. Do diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 491f55ccaf3..a92d58ef9e8 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -28,8 +28,6 @@ use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, outp use serde::Deserialize; #[cfg(feature = "tracing")] use tracing::{instrument, span}; -#[cfg(feature = "tracing")] -use tracing::{instrument, span}; use crate::core::build_steps::llvm; use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index f39e7b02ccc..285d20917e7 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -39,8 +39,6 @@ pub use toml::BUILDER_CONFIG_FILENAME; pub use toml::change_id::ChangeId; pub use toml::rust::LldMode; pub use toml::target::Target; -#[cfg(feature = "tracing")] -use tracing::{instrument, span}; use crate::Display; use crate::str::FromStr; diff --git a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile index 11a66a1c013..a1d04bd984c 100644 --- a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile @@ -30,6 +30,7 @@ ENV SCRIPT \ python3 ../x.py check && \ python3 ../x.py clippy ci && \ python3 ../x.py test --stage 1 core alloc std test proc_macro && \ + python3 ../x.py doc --stage 0 bootstrap && \ # Build both public and internal documentation. RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library && \ diff --git a/src/ci/scripts/create-doc-artifacts.sh b/src/ci/scripts/create-doc-artifacts.sh index 2516b0d8505..487a9ba428f 100755 --- a/src/ci/scripts/create-doc-artifacts.sh +++ b/src/ci/scripts/create-doc-artifacts.sh @@ -15,7 +15,8 @@ fi branch=$(git branch --show-current || echo) if [ -n "$branch" ]; then - branch="${branch}-" + # Strip automation/bors/ prefix if present + branch="${branch#automation/bors/}-" fi if [ "${GITHUB_EVENT_NAME:=none}" = "pull_request" ]; then diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index 6ec93d1746c..65e6b417427 100644 --- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -143,15 +143,6 @@ But if you include this: it will not. -### `test(attr(...))` - -This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For -example, if you want your doctests to fail if they have dead code, you could add this: - -```rust,no_run -#![doc(test(attr(deny(dead_code))))] -``` - ## At the item level These forms of the `#[doc]` attribute are used on individual items, to control how @@ -283,3 +274,26 @@ To get around this limitation, we just add `#[doc(alias = "lib_name_do_something on the `do_something` method and then it's all good! Users can now look for `lib_name_do_something` in our crate directly and find `Obj::do_something`. + +### `test(attr(...))` + +This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For +example, if you want your doctests to fail if they have dead code, you could add this: + +```rust,no_run +#![doc(test(attr(deny(dead_code))))] + +mod my_mod { + #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module +} +``` + +`test(attr(..))` attributes are appended to the parent module's, they do not replace the current +list of attributes. In the previous example, both attributes would be present: + +```rust,no_run +// For every doctest in `my_mod` + +#![deny(dead_code)] // from the crate-root +#![allow(dead_code)] // from `my_mod` +``` diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index b2fe24db0a2..a81d6020f71 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -5,6 +5,7 @@ mod runner; mod rust; use std::fs::File; +use std::hash::{Hash, Hasher}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; @@ -14,7 +15,7 @@ use std::{panic, str}; pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder}; pub(crate) use markdown::test as test_markdown; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHasher, FxIndexMap, FxIndexSet}; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, DiagCtxtHandle}; use rustc_hir as hir; @@ -45,8 +46,6 @@ pub(crate) struct GlobalTestOptions { /// Whether inserting extra indent spaces in code block, /// default is `false`, only `true` for generating code link of Rust playground pub(crate) insert_indent_space: bool, - /// Additional crate-level attributes to add to doctests. - pub(crate) attrs: Vec<String>, /// Path to file containing arguments for the invocation of rustc. pub(crate) args_file: PathBuf, } @@ -283,7 +282,7 @@ pub(crate) fn run_tests( rustdoc_options: &Arc<RustdocOptions>, unused_extern_reports: &Arc<Mutex<Vec<UnusedExterns>>>, mut standalone_tests: Vec<test::TestDescAndFn>, - mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>, + mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>, // We pass this argument so we can drop it manually before using `exit`. mut temp_dir: Option<TempDir>, ) { @@ -298,7 +297,7 @@ pub(crate) fn run_tests( let mut ran_edition_tests = 0; let target_str = rustdoc_options.target.to_string(); - for (edition, mut doctests) in mergeable_tests { + for (MergeableTestKey { edition, global_crate_attrs_hash }, mut doctests) in mergeable_tests { if doctests.is_empty() { continue; } @@ -308,8 +307,8 @@ pub(crate) fn run_tests( let rustdoc_test_options = IndividualTestOptions::new( rustdoc_options, - &Some(format!("merged_doctest_{edition}")), - PathBuf::from(format!("doctest_{edition}.rs")), + &Some(format!("merged_doctest_{edition}_{global_crate_attrs_hash}")), + PathBuf::from(format!("doctest_{edition}_{global_crate_attrs_hash}.rs")), ); for (doctest, scraped_test) in &doctests { @@ -371,12 +370,9 @@ fn scrape_test_config( attrs: &[hir::Attribute], args_file: PathBuf, ) -> GlobalTestOptions { - use rustc_ast_pretty::pprust; - let mut opts = GlobalTestOptions { crate_name, no_crate_inject: false, - attrs: Vec::new(), insert_indent_space: false, args_file, }; @@ -393,13 +389,7 @@ fn scrape_test_config( if attr.has_name(sym::no_crate_inject) { opts.no_crate_inject = true; } - if attr.has_name(sym::attr) - && let Some(l) = attr.meta_item_list() - { - for item in l { - opts.attrs.push(pprust::meta_list_item_to_string(item)); - } - } + // NOTE: `test(attr(..))` is handled when discovering the individual tests } opts @@ -848,6 +838,7 @@ pub(crate) struct ScrapedDocTest { text: String, name: String, span: Span, + global_crate_attrs: Vec<String>, } impl ScrapedDocTest { @@ -858,6 +849,7 @@ impl ScrapedDocTest { langstr: LangString, text: String, span: Span, + global_crate_attrs: Vec<String>, ) -> Self { let mut item_path = logical_path.join("::"); item_path.retain(|c| c != ' '); @@ -867,7 +859,7 @@ impl ScrapedDocTest { let name = format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly()); - Self { filename, line, langstr, text, name, span } + Self { filename, line, langstr, text, name, span, global_crate_attrs } } fn edition(&self, opts: &RustdocOptions) -> Edition { self.langstr.edition.unwrap_or(opts.edition) @@ -896,9 +888,15 @@ pub(crate) trait DocTestVisitor { fn visit_header(&mut self, _name: &str, _level: u32) {} } +#[derive(Clone, Debug, Hash, Eq, PartialEq)] +pub(crate) struct MergeableTestKey { + edition: Edition, + global_crate_attrs_hash: u64, +} + struct CreateRunnableDocTests { standalone_tests: Vec<test::TestDescAndFn>, - mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>, + mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>, rustdoc_options: Arc<RustdocOptions>, opts: GlobalTestOptions, @@ -949,6 +947,7 @@ impl CreateRunnableDocTests { let edition = scraped_test.edition(&self.rustdoc_options); let doctest = BuildDocTestBuilder::new(&scraped_test.text) .crate_name(&self.opts.crate_name) + .global_crate_attrs(scraped_test.global_crate_attrs.clone()) .edition(edition) .can_merge_doctests(self.can_merge_doctests) .test_id(test_id) @@ -965,7 +964,17 @@ impl CreateRunnableDocTests { let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test); self.standalone_tests.push(test_desc); } else { - self.mergeable_tests.entry(edition).or_default().push((doctest, scraped_test)); + self.mergeable_tests + .entry(MergeableTestKey { + edition, + global_crate_attrs_hash: { + let mut hasher = FxHasher::default(); + scraped_test.global_crate_attrs.hash(&mut hasher); + hasher.finish() + }, + }) + .or_default() + .push((doctest, scraped_test)); } } diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs index 3b17ccc78c7..ebe6bfd22ba 100644 --- a/src/librustdoc/doctest/extracted.rs +++ b/src/librustdoc/doctest/extracted.rs @@ -35,13 +35,16 @@ impl ExtractedDocTests { ) { let edition = scraped_test.edition(options); - let ScrapedDocTest { filename, line, langstr, text, name, .. } = scraped_test; + let ScrapedDocTest { filename, line, langstr, text, name, global_crate_attrs, .. } = + scraped_test; let doctest = BuildDocTestBuilder::new(&text) .crate_name(&opts.crate_name) + .global_crate_attrs(global_crate_attrs) .edition(edition) .lang_str(&langstr) .build(None); + let (full_test_code, size) = doctest.generate_unique_doctest( &text, langstr.test_harness, diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 66647b88018..5e571613d6f 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -45,6 +45,7 @@ pub(crate) struct BuildDocTestBuilder<'a> { test_id: Option<String>, lang_str: Option<&'a LangString>, span: Span, + global_crate_attrs: Vec<String>, } impl<'a> BuildDocTestBuilder<'a> { @@ -57,6 +58,7 @@ impl<'a> BuildDocTestBuilder<'a> { test_id: None, lang_str: None, span: DUMMY_SP, + global_crate_attrs: Vec::new(), } } @@ -96,6 +98,12 @@ impl<'a> BuildDocTestBuilder<'a> { self } + #[inline] + pub(crate) fn global_crate_attrs(mut self, global_crate_attrs: Vec<String>) -> Self { + self.global_crate_attrs = global_crate_attrs; + self + } + pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder { let BuildDocTestBuilder { source, @@ -106,6 +114,7 @@ impl<'a> BuildDocTestBuilder<'a> { test_id, lang_str, span, + global_crate_attrs, } = self; let can_merge_doctests = can_merge_doctests && lang_str.is_some_and(|lang_str| { @@ -133,6 +142,7 @@ impl<'a> BuildDocTestBuilder<'a> { // If the AST returned an error, we don't want this doctest to be merged with the // others. return DocTestBuilder::invalid( + Vec::new(), String::new(), String::new(), String::new(), @@ -155,6 +165,7 @@ impl<'a> BuildDocTestBuilder<'a> { DocTestBuilder { supports_color, has_main_fn, + global_crate_attrs, crate_attrs, maybe_crate_attrs, crates, @@ -173,6 +184,7 @@ pub(crate) struct DocTestBuilder { pub(crate) supports_color: bool, pub(crate) already_has_extern_crate: bool, pub(crate) has_main_fn: bool, + pub(crate) global_crate_attrs: Vec<String>, pub(crate) crate_attrs: String, /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will /// put into `crate_attrs`. @@ -186,6 +198,7 @@ pub(crate) struct DocTestBuilder { impl DocTestBuilder { fn invalid( + global_crate_attrs: Vec<String>, crate_attrs: String, maybe_crate_attrs: String, crates: String, @@ -195,6 +208,7 @@ impl DocTestBuilder { Self { supports_color: false, has_main_fn: false, + global_crate_attrs, crate_attrs, maybe_crate_attrs, crates, @@ -224,7 +238,8 @@ impl DocTestBuilder { let mut line_offset = 0; let mut prog = String::new(); let everything_else = self.everything_else.trim(); - if opts.attrs.is_empty() { + + if self.global_crate_attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in @@ -233,8 +248,8 @@ impl DocTestBuilder { line_offset += 1; } - // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. - for attr in &opts.attrs { + // Next, any attributes that came from #![doc(test(attr(...)))]. + for attr in &self.global_crate_attrs { prog.push_str(&format!("#![{attr}]\n")); line_offset += 1; } diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index e358a7e44e5..7f26605f256 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -31,6 +31,7 @@ impl DocTestVisitor for MdCollector { config, test, DUMMY_SP, + Vec::new(), )); } @@ -96,7 +97,6 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { crate_name, no_crate_inject: true, insert_indent_space: false, - attrs: vec![], args_file, }; diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 39a4f23560a..f0914474c79 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -12,6 +12,7 @@ use crate::html::markdown::{Ignore, LangString}; /// Convenient type to merge compatible doctests into one. pub(crate) struct DocTestRunner { crate_attrs: FxIndexSet<String>, + global_crate_attrs: FxIndexSet<String>, ids: String, output: String, output_merged_tests: String, @@ -23,6 +24,7 @@ impl DocTestRunner { pub(crate) fn new() -> Self { Self { crate_attrs: FxIndexSet::default(), + global_crate_attrs: FxIndexSet::default(), ids: String::new(), output: String::new(), output_merged_tests: String::new(), @@ -46,6 +48,9 @@ impl DocTestRunner { for line in doctest.crate_attrs.split('\n') { self.crate_attrs.insert(line.to_string()); } + for line in &doctest.global_crate_attrs { + self.global_crate_attrs.insert(line.to_string()); + } } self.ids.push_str(&format!( "tests.push({}::TEST);\n", @@ -85,7 +90,7 @@ impl DocTestRunner { code_prefix.push('\n'); } - if opts.attrs.is_empty() { + if self.global_crate_attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in @@ -93,8 +98,8 @@ impl DocTestRunner { code_prefix.push_str("#![allow(unused)]\n"); } - // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. - for attr in &opts.attrs { + // Next, any attributes that came from #![doc(test(attr(...)))]. + for attr in &self.global_crate_attrs { code_prefix.push_str(&format!("#![{attr}]\n")); } diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index f9d2aa3d3b4..96975105ac5 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -4,6 +4,7 @@ use std::cell::Cell; use std::env; use std::sync::Arc; +use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; @@ -11,7 +12,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_resolve::rustdoc::span_of_fragments; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span}; +use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym}; use super::{DocTestVisitor, ScrapedDocTest}; use crate::clean::{Attributes, extract_cfg_from_attrs}; @@ -22,6 +23,7 @@ struct RustCollector { tests: Vec<ScrapedDocTest>, cur_path: Vec<String>, position: Span, + global_crate_attrs: Vec<String>, } impl RustCollector { @@ -75,6 +77,7 @@ impl DocTestVisitor for RustCollector { config, test, span, + self.global_crate_attrs.clone(), )); } @@ -94,6 +97,7 @@ impl<'tcx> HirCollector<'tcx> { cur_path: vec![], position: DUMMY_SP, tests: vec![], + global_crate_attrs: Vec::new(), }; Self { codes, tcx, collector } } @@ -123,6 +127,26 @@ impl HirCollector<'_> { return; } + // Try collecting `#[doc(test(attr(...)))]` + let old_global_crate_attrs_len = self.collector.global_crate_attrs.len(); + for doc_test_attrs in ast_attrs + .iter() + .filter(|a| a.has_name(sym::doc)) + .flat_map(|a| a.meta_item_list().unwrap_or_default()) + .filter(|a| a.has_name(sym::test)) + { + let Some(doc_test_attrs) = doc_test_attrs.meta_item_list() else { continue }; + for attr in doc_test_attrs + .iter() + .filter(|a| a.has_name(sym::attr)) + .flat_map(|a| a.meta_item_list().unwrap_or_default()) + .map(|i| pprust::meta_list_item_to_string(i)) + { + // Add the additional attributes to the global_crate_attrs vector + self.collector.global_crate_attrs.push(attr); + } + } + let mut has_name = false; if let Some(name) = name { self.collector.cur_path.push(name); @@ -157,6 +181,9 @@ impl HirCollector<'_> { nested(self); + // Restore global_crate_attrs to it's previous size/content + self.collector.global_crate_attrs.truncate(old_global_crate_attrs_len); + if has_name { self.collector.cur_path.pop(); } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 08248fdf39b..ce2984ced79 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -7,9 +7,11 @@ fn make_test( crate_name: Option<&str>, dont_insert_main: bool, opts: &GlobalTestOptions, + global_crate_attrs: Vec<&str>, test_id: Option<&str>, ) -> (String, usize) { - let mut builder = BuildDocTestBuilder::new(test_code); + let mut builder = BuildDocTestBuilder::new(test_code) + .global_crate_attrs(global_crate_attrs.into_iter().map(|a| a.to_string()).collect()); if let Some(crate_name) = crate_name { builder = builder.crate_name(crate_name); } @@ -28,7 +30,6 @@ fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions { crate_name: crate_name.into(), no_crate_inject: false, insert_indent_space: false, - attrs: vec![], args_file: PathBuf::new(), } } @@ -43,7 +44,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -58,7 +59,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -77,7 +78,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 3)); } @@ -94,7 +95,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -112,7 +113,7 @@ use std::*; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("std"), false, &opts, None); + let (output, len) = make_test(input, Some("std"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -131,7 +132,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -148,7 +149,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -156,8 +157,7 @@ assert_eq!(2+2, 4); fn make_test_opts_attrs() { // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use // those instead of the stock `#![allow(unused)]`. - let mut opts = default_global_opts("asdf"); - opts.attrs.push("feature(sick_rad)".to_string()); + let opts = default_global_opts("asdf"); let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![feature(sick_rad)] @@ -168,11 +168,10 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = + make_test(input, Some("asdf"), false, &opts, vec!["feature(sick_rad)"], None); assert_eq!((output, len), (expected, 3)); - // Adding more will also bump the returned line offset. - opts.attrs.push("feature(hella_dope)".to_string()); let expected = "#![feature(sick_rad)] #![feature(hella_dope)] #[allow(unused_extern_crates)] @@ -182,7 +181,18 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test( + input, + Some("asdf"), + false, + &opts, + vec![ + "feature(sick_rad)", + // Adding more will also bump the returned line offset. + "feature(hella_dope)", + ], + None, + ); assert_eq!((output, len), (expected, 4)); } @@ -200,7 +210,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -216,7 +226,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -232,7 +242,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -246,7 +256,7 @@ assert_eq!(2+2, 4);"; //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);" .to_string(); - let (output, len) = make_test(input, None, true, &opts, None); + let (output, len) = make_test(input, None, true, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -264,7 +274,7 @@ assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -284,7 +294,7 @@ assert_eq!(asdf::foo, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 3)); } @@ -302,7 +312,7 @@ test_wrapper! { }" .to_string(); - let (output, len) = make_test(input, Some("my_crate"), false, &opts, None); + let (output, len) = make_test(input, Some("my_crate"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -322,7 +332,7 @@ io::stdin().read_line(&mut input)?; Ok::<(), io:Error>(()) } _inner().unwrap() }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -336,7 +346,7 @@ fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() { assert_eq!(2+2, 4); } _doctest_main__some_unique_name() }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, Some("_some_unique_name")); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), Some("_some_unique_name")); assert_eq!((output, len), (expected, 2)); } @@ -355,7 +365,7 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -375,7 +385,7 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -400,7 +410,7 @@ fn main() { }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); // And same, if there is a `main` function provided by the user, we ensure that it's @@ -420,7 +430,7 @@ fn main() {}"; fn main() {}" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -448,6 +458,6 @@ pub mod outer_module { } }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 68ba1245520..d3701784f9d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -300,7 +300,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> { crate_name: krate.map(String::from).unwrap_or_default(), no_crate_inject: false, insert_indent_space: true, - attrs: vec![], args_file: PathBuf::new(), }; let mut builder = doctest::BuildDocTestBuilder::new(&test).edition(edition); diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 741d7e3fa16..f8209f2c8cd 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -40,7 +40,9 @@ static HOSTS: &[&str] = &[ "powerpc64le-unknown-linux-musl", "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", + "sparcv9-sun-solaris", "x86_64-apple-darwin", + "x86_64-pc-solaris", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", "x86_64-unknown-freebsd", diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 84a353bfbcf..d1a5ef7b7fc 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -775e0c8aeb8f63192854b27156f8b05a06b51814 +a5584a8fe16037dc01782064fa41424a6dbe9987 diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs index 48633c0a7fe..8936ae8e912 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs @@ -2,8 +2,6 @@ //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+aes,+vaes,+avx512f -#![feature(stdarch_x86_avx512)] - use core::mem::transmute; #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs index 0ec2f679d80..65d7b57d1ce 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs @@ -2,8 +2,6 @@ //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq -#![feature(stdarch_x86_avx512)] - #[cfg(target_arch = "x86")] use std::arch::x86::*; #[cfg(target_arch = "x86_64")] diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs index b58d68e2ef9..48958ef5810 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs @@ -6,7 +6,6 @@ // be interpreted as integers; signedness does not make sense for them, but // __mXXXi happens to be defined in terms of signed integers. #![allow(overflowing_literals)] -#![feature(stdarch_x86_avx512)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs index c7c9eb5e395..e2a045bf81f 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs @@ -8,7 +8,6 @@ // be interpreted as integers; signedness does not make sense for them, but // __mXXXi happens to be defined in terms of signed integers. #![allow(overflowing_literals)] -#![feature(stdarch_x86_avx512)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index f9ff3921266..de8a42979bb 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -4458,20 +4458,6 @@ The tracking issue for this feature is: [#133214] deny_since: None, }, Lint { - label: "const_eq_ignore_ascii_case", - description: r##"# `const_eq_ignore_ascii_case` - -The tracking issue for this feature is: [#131719] - -[#131719]: https://github.com/rust-lang/rust/issues/131719 - ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { label: "const_eval_select", description: r##"# `const_eval_select` diff --git a/tests/run-make/doctests-keep-binaries-2024/rmake.rs b/tests/run-make/doctests-keep-binaries-2024/rmake.rs index 3e8ffcbf244..97324e1dcbc 100644 --- a/tests/run-make/doctests-keep-binaries-2024/rmake.rs +++ b/tests/run-make/doctests-keep-binaries-2024/rmake.rs @@ -16,7 +16,22 @@ fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) { } fn check_generated_binaries() { - run("doctests/merged_doctest_2024/rust_out"); + let mut found_merged_doctest = false; + rfs::read_dir_entries("doctests/", |path| { + if path + .file_name() + .and_then(|name| name.to_str()) + .is_some_and(|name| name.starts_with("merged_doctest_2024")) + { + found_merged_doctest = true; + let rust_out = path.join("rust_out"); + let rust_out = rust_out.to_string_lossy(); + run(&*rust_out); + } + }); + if !found_merged_doctest { + panic!("no directory starting with `merged_doctest_2024` found under `doctests/`"); + } } fn main() { diff --git a/tests/rustdoc-ui/doctest/dead-code-items.rs b/tests/rustdoc-ui/doctest/dead-code-items.rs new file mode 100644 index 00000000000..015504cbced --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-items.rs @@ -0,0 +1,116 @@ +// Same test as dead-code-module but with 2 doc(test(attr())) at different levels. + +//@ edition: 2024 +//@ compile-flags:--test --test-args=--test-threads=1 +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +#![doc(test(attr(deny(warnings))))] + +#[doc(test(attr(allow(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarning { fn no_deny_warnings(); } +/// ``` +static S: u32 = 5; + +#[doc(test(attr(allow(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// let unused_error = 5; +/// +/// fn dead_code_but_no_error() {} +/// ``` +const C: u32 = 5; + +#[doc(test(attr(allow(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarningAtA { fn no_deny_warnings(); } +/// ``` +struct A { + #[doc(test(attr(deny(dead_code))))] + /// Example + /// + /// ```rust,no_run + /// trait DeadCodeInField {} + /// ``` + field: u32 +} + +#[doc(test(attr(allow(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarningAtU { fn no_deny_warnings(); } +/// ``` +union U { + #[doc(test(attr(deny(dead_code))))] + /// Example + /// + /// ```rust,no_run + /// trait DeadCodeInUnionField {} + /// ``` + field: u32, + /// Example + /// + /// ```rust,no_run + /// trait NotDeadCodeInUnionField {} + /// ``` + field2: u64, +} + +#[doc(test(attr(deny(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// let not_dead_code_but_unused = 5; +/// ``` +enum Enum { + #[doc(test(attr(allow(dead_code))))] + /// Example + /// + /// ```rust,no_run + /// trait NotDeadCodeInVariant {} + /// + /// fn main() { let unused_in_variant = 5; } + /// ``` + Variant1, +} + +#[doc(test(attr(allow(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarningAtImplA { fn no_deny_warnings(); } +/// ``` +impl A { + /// Example + /// + /// ```rust,no_run + /// trait NotDeadCodeInImplMethod {} + /// ``` + fn method() {} +} + +#[doc(test(attr(deny(dead_code))))] +/// Example +/// +/// ```rust,no_run +/// trait StillDeadCodeAtMyTrait { } +/// ``` +trait MyTrait { + #[doc(test(attr(allow(dead_code))))] + /// Example + /// + /// ```rust,no_run + /// trait NotDeadCodeAtImplFn {} + /// + /// fn main() { let unused_in_impl = 5; } + /// ``` + fn my_trait_fn(); +} diff --git a/tests/rustdoc-ui/doctest/dead-code-items.stdout b/tests/rustdoc-ui/doctest/dead-code-items.stdout new file mode 100644 index 00000000000..4b9d8be94dd --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-items.stdout @@ -0,0 +1,146 @@ + +running 13 tests +test $DIR/dead-code-items.rs - A (line 32) - compile ... ok +test $DIR/dead-code-items.rs - A (line 88) - compile ... ok +test $DIR/dead-code-items.rs - A::field (line 39) - compile ... FAILED +test $DIR/dead-code-items.rs - A::method (line 94) - compile ... ok +test $DIR/dead-code-items.rs - C (line 22) - compile ... FAILED +test $DIR/dead-code-items.rs - Enum (line 70) - compile ... FAILED +test $DIR/dead-code-items.rs - Enum::Variant1 (line 77) - compile ... FAILED +test $DIR/dead-code-items.rs - MyTrait (line 103) - compile ... FAILED +test $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) - compile ... FAILED +test $DIR/dead-code-items.rs - S (line 14) - compile ... ok +test $DIR/dead-code-items.rs - U (line 48) - compile ... ok +test $DIR/dead-code-items.rs - U::field (line 55) - compile ... FAILED +test $DIR/dead-code-items.rs - U::field2 (line 61) - compile ... ok + +failures: + +---- $DIR/dead-code-items.rs - A::field (line 39) stdout ---- +error: trait `DeadCodeInField` is never used + --> $DIR/dead-code-items.rs:40:7 + | +LL | trait DeadCodeInField {} + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:38:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - C (line 22) stdout ---- +error: unused variable: `unused_error` + --> $DIR/dead-code-items.rs:23:5 + | +LL | let unused_error = 5; + | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_error` + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:20:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - Enum (line 70) stdout ---- +error: unused variable: `not_dead_code_but_unused` + --> $DIR/dead-code-items.rs:71:5 + | +LL | let not_dead_code_but_unused = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_not_dead_code_but_unused` + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:68:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - Enum::Variant1 (line 77) stdout ---- +error: unused variable: `unused_in_variant` + --> $DIR/dead-code-items.rs:80:17 + | +LL | fn main() { let unused_in_variant = 5; } + | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_variant` + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:75:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - MyTrait (line 103) stdout ---- +error: trait `StillDeadCodeAtMyTrait` is never used + --> $DIR/dead-code-items.rs:104:7 + | +LL | trait StillDeadCodeAtMyTrait { } + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:102:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) stdout ---- +error: unused variable: `unused_in_impl` + --> $DIR/dead-code-items.rs:113:17 + | +LL | fn main() { let unused_in_impl = 5; } + | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_impl` + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:108:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. +---- $DIR/dead-code-items.rs - U::field (line 55) stdout ---- +error: trait `DeadCodeInUnionField` is never used + --> $DIR/dead-code-items.rs:56:7 + | +LL | trait DeadCodeInUnionField {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/dead-code-items.rs:54:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/dead-code-items.rs - A::field (line 39) + $DIR/dead-code-items.rs - C (line 22) + $DIR/dead-code-items.rs - Enum (line 70) + $DIR/dead-code-items.rs - Enum::Variant1 (line 77) + $DIR/dead-code-items.rs - MyTrait (line 103) + $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) + $DIR/dead-code-items.rs - U::field (line 55) + +test result: FAILED. 6 passed; 7 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.rs b/tests/rustdoc-ui/doctest/dead-code-module-2.rs new file mode 100644 index 00000000000..de7b11b91ec --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module-2.rs @@ -0,0 +1,27 @@ +// Same test as dead-code-module but with 2 doc(test(attr())) at different levels. + +//@ edition: 2024 +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +#![doc(test(attr(allow(unused_variables))))] + +mod my_mod { + #![doc(test(attr(deny(warnings))))] + + /// Example + /// + /// ```rust,no_run + /// trait T { fn f(); } + /// ``` + pub fn f() {} +} + +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarning { fn no_deny_warnings(); } +/// ``` +pub fn g() {} diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.stdout b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout new file mode 100644 index 00000000000..d44068dcbf5 --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout @@ -0,0 +1,35 @@ + +running 1 test +test $DIR/dead-code-module-2.rs - g (line 24) - compile ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 1 test +test $DIR/dead-code-module-2.rs - my_mod::f (line 16) - compile ... FAILED + +failures: + +---- $DIR/dead-code-module-2.rs - my_mod::f (line 16) stdout ---- +error: trait `T` is never used + --> $DIR/dead-code-module-2.rs:17:7 + | +LL | trait T { fn f(); } + | ^ + | +note: the lint level is defined here + --> $DIR/dead-code-module-2.rs:15:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/dead-code-module-2.rs - my_mod::f (line 16) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/dead-code-module.rs b/tests/rustdoc-ui/doctest/dead-code-module.rs new file mode 100644 index 00000000000..f825749a6a2 --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module.rs @@ -0,0 +1,18 @@ +// Same test as dead-code but inside a module. + +//@ edition: 2024 +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +mod my_mod { + #![doc(test(attr(allow(unused_variables), deny(warnings))))] + + /// Example + /// + /// ```rust,no_run + /// trait T { fn f(); } + /// ``` + pub fn f() {} +} diff --git a/tests/rustdoc-ui/doctest/dead-code-module.stdout b/tests/rustdoc-ui/doctest/dead-code-module.stdout new file mode 100644 index 00000000000..b5ccf225d25 --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module.stdout @@ -0,0 +1,29 @@ + +running 1 test +test $DIR/dead-code-module.rs - my_mod::f (line 14) - compile ... FAILED + +failures: + +---- $DIR/dead-code-module.rs - my_mod::f (line 14) stdout ---- +error: trait `T` is never used + --> $DIR/dead-code-module.rs:15:7 + | +LL | trait T { fn f(); } + | ^ + | +note: the lint level is defined here + --> $DIR/dead-code-module.rs:13:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/dead-code-module.rs - my_mod::f (line 14) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs new file mode 100644 index 00000000000..e916ca41ea0 --- /dev/null +++ b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs @@ -0,0 +1,11 @@ +//@ check-pass + +#![crate_type = "lib"] +#![deny(invalid_doc_attributes)] +#![doc(test(no_crate_inject))] + +mod my_mod { + #![doc(test(attr(deny(warnings))))] + + pub fn foo() {} +} diff --git a/tests/ui/asm/x86_64/evex512-implicit-feature.rs b/tests/ui/asm/x86_64/evex512-implicit-feature.rs index ec5da7c7fa4..1f678b2387a 100644 --- a/tests/ui/asm/x86_64/evex512-implicit-feature.rs +++ b/tests/ui/asm/x86_64/evex512-implicit-feature.rs @@ -2,8 +2,6 @@ //@ only-x86_64 //@ compile-flags: --crate-type=lib -C target-cpu=skylake -#![feature(stdarch_x86_avx512)] - use std::arch::x86_64::*; #[target_feature(enable = "avx512f")] diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr index 8c9d06c79ca..40d44db205f 100644 --- a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr +++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr @@ -2,14 +2,16 @@ error[E0277]: `[usize; usize::MAX]` is not a future --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:8:37 | LL | [0usize; 0xffff_ffff_ffff_ffff].await; - | -^^^^^ - | || - | |`[usize; usize::MAX]` is not a future - | help: remove the `.await` + | ^^^^^ `[usize; usize::MAX]` is not a future | = help: the trait `Future` is not implemented for `[usize; usize::MAX]` = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited = note: required for `[usize; usize::MAX]` to implement `IntoFuture` +help: remove the `.await` + | +LL - [0usize; 0xffff_ffff_ffff_ffff].await; +LL + [0usize; 0xffff_ffff_ffff_ffff]; + | error[E0752]: `main` function is not allowed to be `async` --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:6:1 diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr index 721e0106293..644a7c7717c 100644 --- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -10,14 +10,16 @@ error[E0277]: `Option<_>` is not a future --> $DIR/drop-track-bad-field-in-fru.rs:6:46 | LL | None { value: (), ..Default::default() }.await; - | -^^^^^ - | || - | |`Option<_>` is not a future - | help: remove the `.await` + | ^^^^^ `Option<_>` is not a future | = help: the trait `Future` is not implemented for `Option<_>` = note: Option<_> must be a future or must implement `IntoFuture` to be awaited = note: required for `Option<_>` to implement `IntoFuture` +help: remove the `.await` + | +LL - None { value: (), ..Default::default() }.await; +LL + None { value: (), ..Default::default() }; + | error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr index f6af15c00d6..87302dce130 100644 --- a/tests/ui/async-await/issue-101715.stderr +++ b/tests/ui/async-await/issue-101715.stderr @@ -2,14 +2,15 @@ error[E0277]: `()` is not a future --> $DIR/issue-101715.rs:11:10 | LL | .await - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` + | ^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - .await + | error: aborting due to 1 previous error diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr index 620370a6113..f60b4ecb990 100644 --- a/tests/ui/async-await/unnecessary-await.stderr +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -23,14 +23,16 @@ error[E0277]: `()` is not a future --> $DIR/unnecessary-await.rs:28:10 | LL | e!().await; - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` + | ^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - e!().await; +LL + e!(); + | error[E0277]: `()` is not a future --> $DIR/unnecessary-await.rs:22:15 @@ -53,14 +55,16 @@ error[E0277]: `()` is not a future --> $DIR/unnecessary-await.rs:36:20 | LL | for x in [] {}.await - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` + | ^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - for x in [] {}.await +LL + for x in [] {} + | error: aborting due to 4 previous errors diff --git a/tests/ui/cast/cast-to-slice.stderr b/tests/ui/cast/cast-to-slice.stderr index 8f862c00014..382ccc3d10c 100644 --- a/tests/ui/cast/cast-to-slice.stderr +++ b/tests/ui/cast/cast-to-slice.stderr @@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[u8]` as `[char]` --> $DIR/cast-to-slice.rs:2:5 | LL | "example".as_bytes() as [char]; - | ^^^^^^^^^^^^^^^^^^^^^^^^------ - | | - | help: try casting to a reference instead: `&[char]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider casting to a reference instead + | +LL | "example".as_bytes() as &[char]; + | + error[E0620]: cast to unsized type: `&[u8]` as `[char]` --> $DIR/cast-to-slice.rs:6:5 | LL | arr as [char]; - | ^^^^^^^------ - | | - | help: try casting to a reference instead: `&[char]` + | ^^^^^^^^^^^^^ + | +help: consider casting to a reference instead + | +LL | arr as &[char]; + | + error: aborting due to 2 previous errors diff --git a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr index 3b5b8ea69c1..2803c3380d7 100644 --- a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr +++ b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr @@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&{integer}` as `dyn Send` --> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5 | LL | &1 as dyn Send; - | ^^^^^^-------- - | | - | help: try casting to a reference instead: `&dyn Send` + | ^^^^^^^^^^^^^^ + | +help: consider casting to a reference instead + | +LL | &1 as &dyn Send; + | + error[E0620]: cast to unsized type: `Box<{integer}>` as `dyn Send` --> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5 | LL | Box::new(1) as dyn Send; - | ^^^^^^^^^^^^^^^-------- - | | - | help: you can cast to a `Box` instead: `Box<dyn Send>` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: you can cast to a `Box` instead + | +LL | Box::new(1) as Box<dyn Send>; + | ++++ + error: aborting due to 2 previous errors diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr index a287aa29e11..891931d0bf8 100644 --- a/tests/ui/coercion/issue-73886.stderr +++ b/tests/ui/coercion/issue-73886.stderr @@ -10,9 +10,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>` --> $DIR/issue-73886.rs:4:13 | LL | let _ = 7u32 as Option<_>; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object help: consider using the `From` trait instead | LL - let _ = 7u32 as Option<_>; diff --git a/tests/ui/coercion/non-primitive-cast-135412.stderr b/tests/ui/coercion/non-primitive-cast-135412.stderr index 7e5861f83e9..e5e9ee13459 100644 --- a/tests/ui/coercion/non-primitive-cast-135412.stderr +++ b/tests/ui/coercion/non-primitive-cast-135412.stderr @@ -2,9 +2,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>` --> $DIR/non-primitive-cast-135412.rs:6:13 | LL | let _ = 7u32 as Option<_>; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object help: consider using the `From` trait instead | LL - let _ = 7u32 as Option<_>; @@ -15,9 +14,8 @@ error[E0605]: non-primitive cast: `&'static str` as `Arc<str>` --> $DIR/non-primitive-cast-135412.rs:8:13 | LL | let _ = "String" as Arc<str>; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object help: consider using the `From` trait instead | LL - let _ = "String" as Arc<str>; diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index a3d5054ced3..54982391b66 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -13,9 +13,8 @@ LL | struct Bar; | help: create an inline `const` block | -LL - let _: [Option<Bar>; 2] = [no_copy(); 2]; -LL + let _: [Option<Bar>; 2] = [const { no_copy() }; 2]; - | +LL | let _: [Option<Bar>; 2] = [const { no_copy() }; 2]; + | +++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 58ddc047d03..601d067e3d8 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -2,10 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/trait-error.rs:5:6 | LL | [Foo(String::new()); 4]; - | ^^^^^^^^^^^^^^^^^^ - | | - | the trait `Copy` is not implemented for `String` - | help: create an inline `const` block: `const { Foo(String::new()) }` + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required for `Foo<String>` to implement `Copy` --> $DIR/trait-error.rs:1:10 @@ -13,6 +10,10 @@ note: required for `Foo<String>` to implement `Copy` LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the `Copy` trait is required because this value will be copied for each element of the array +help: create an inline `const` block + | +LL | [const { Foo(String::new()) }; 4]; + | +++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr index 1a0832b8ba0..b996370ea3d 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -23,7 +23,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8` LL | : [u32; 5i8 as char as usize] | ^^^^^^^^^^^ invalid cast | -help: try casting from `u8` instead +help: consider casting from `u8` instead --> $DIR/const-eval-overflow-4b.rs:24:13 | LL | : [u32; 5i8 as char as usize] diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 5be26d7c121..890eb8040b9 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -2,36 +2,39 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:1:47 | LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5]; - | ^^^^ - | | - | the trait `Copy` is not implemented for `String` - | help: create an inline `const` block: `const { None }` + | ^^^^ the trait `Copy` is not implemented for `String` | = note: required for `Option<String>` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array +help: create an inline `const` block + | +LL | static _MAYBE_STRINGS: [Option<String>; 5] = [const { None }; 5]; + | +++++++ + error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:7:34 | LL | let _strings: [String; 5] = [String::new(); 5]; - | ^^^^^^^^^^^^^ - | | - | the trait `Copy` is not implemented for `String` - | help: create an inline `const` block: `const { String::new() }` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because this value will be copied for each element of the array +help: create an inline `const` block + | +LL | let _strings: [String; 5] = [const { String::new() }; 5]; + | +++++++ + error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:12:48 | LL | let _maybe_strings: [Option<String>; 5] = [None; 5]; - | ^^^^ - | | - | the trait `Copy` is not implemented for `String` - | help: create an inline `const` block: `const { None }` + | ^^^^ the trait `Copy` is not implemented for `String` | = note: required for `Option<String>` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array +help: create an inline `const` block + | +LL | let _maybe_strings: [Option<String>; 5] = [const { None }; 5]; + | +++++++ + error: aborting due to 3 previous errors diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr index da2ec272f9f..86b73e4b062 100644 --- a/tests/ui/coroutine/unresolved-ct-var.stderr +++ b/tests/ui/coroutine/unresolved-ct-var.stderr @@ -2,15 +2,18 @@ error[E0277]: `[(); _]` is not a future --> $DIR/unresolved-ct-var.rs:6:45 | LL | let s = std::array::from_fn(|_| ()).await; - | ----------------------------^^^^^ - | | || - | | |`[(); _]` is not a future - | | help: remove the `.await` + | --------------------------- ^^^^^ `[(); _]` is not a future + | | | this call returns `[(); _]` | = help: the trait `Future` is not implemented for `[(); _]` = note: [(); _] must be a future or must implement `IntoFuture` to be awaited = note: required for `[(); _]` to implement `IntoFuture` +help: remove the `.await` + | +LL - let s = std::array::from_fn(|_| ()).await; +LL + let s = std::array::from_fn(|_| ()); + | error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0604.stderr b/tests/ui/error-codes/E0604.stderr index e91f74d6b3f..67bbb25958f 100644 --- a/tests/ui/error-codes/E0604.stderr +++ b/tests/ui/error-codes/E0604.stderr @@ -2,10 +2,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/E0604.rs:2:5 | LL | 1u32 as char; - | ^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(1u32)` + | ^^^^^^^^^^^^ invalid cast + | +help: consider using `char::from_u32` instead + | +LL - 1u32 as char; +LL + char::from_u32(1u32); + | error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0620.stderr b/tests/ui/error-codes/E0620.stderr index 644ba813c96..696407c6f7e 100644 --- a/tests/ui/error-codes/E0620.stderr +++ b/tests/ui/error-codes/E0620.stderr @@ -2,9 +2,12 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]` --> $DIR/E0620.rs:2:16 | LL | let _foo = &[1_usize, 2] as [usize]; - | ^^^^^^^^^^^^^^^^^------- - | | - | help: try casting to a reference instead: `&[usize]` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider casting to a reference instead + | +LL | let _foo = &[1_usize, 2] as &[usize]; + | + error: aborting due to 1 previous error diff --git a/tests/ui/error-emitter/error-festival.stderr b/tests/ui/error-emitter/error-festival.stderr index be484bc8094..6c661eb17a8 100644 --- a/tests/ui/error-emitter/error-festival.stderr +++ b/tests/ui/error-emitter/error-festival.stderr @@ -58,10 +58,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/error-festival.rs:27:5 | LL | 0u32 as char; - | ^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(0u32)` + | ^^^^^^^^^^^^ invalid cast + | +help: consider using `char::from_u32` instead + | +LL - 0u32 as char; +LL + char::from_u32(0u32); + | error[E0605]: non-primitive cast: `u8` as `Vec<u8>` --> $DIR/error-festival.rs:31:5 diff --git a/tests/ui/future-incompatible-lint-group.rs b/tests/ui/future-incompatible-lint-group.rs index c84538318f7..ed2c47bb609 100644 --- a/tests/ui/future-incompatible-lint-group.rs +++ b/tests/ui/future-incompatible-lint-group.rs @@ -2,16 +2,14 @@ // lints for changes that are not tied to an edition #![deny(future_incompatible)] +// Error since this is a `future_incompatible` lint +macro_rules! m { ($i) => {} } //~ ERROR missing fragment specifier + //~| WARN this was previously accepted + trait Tr { // Warn only since this is not a `future_incompatible` lint fn f(u8) {} //~ WARN anonymous parameters are deprecated //~| WARN this is accepted in the current edition } -pub mod submodule { - // Error since this is a `future_incompatible` lint - #![doc(test(some_test))] - //~^ ERROR this attribute can only be applied at the crate level -} - fn main() {} diff --git a/tests/ui/future-incompatible-lint-group.stderr b/tests/ui/future-incompatible-lint-group.stderr index 4e6c434fa29..4c867e0aab3 100644 --- a/tests/ui/future-incompatible-lint-group.stderr +++ b/tests/ui/future-incompatible-lint-group.stderr @@ -1,5 +1,20 @@ +error: missing fragment specifier + --> $DIR/future-incompatible-lint-group.rs:6:19 + | +LL | macro_rules! m { ($i) => {} } + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> +note: the lint level is defined here + --> $DIR/future-incompatible-lint-group.rs:3:9 + | +LL | #![deny(future_incompatible)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]` + warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/future-incompatible-lint-group.rs:7:10 + --> $DIR/future-incompatible-lint-group.rs:11:10 | LL | fn f(u8) {} | ^^ help: try naming the parameter or explicitly ignoring it: `_: u8` @@ -8,14 +23,21 @@ LL | fn f(u8) {} = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686> = note: `#[warn(anonymous_parameters)]` on by default -error: this attribute can only be applied at the crate level - --> $DIR/future-incompatible-lint-group.rs:13:12 +error: aborting due to 1 previous error; 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +error: missing fragment specifier + --> $DIR/future-incompatible-lint-group.rs:6:19 | -LL | #![doc(test(some_test))] - | ^^^^^^^^^^^^^^^ +LL | macro_rules! m { ($i) => {} } + | ^^ | - = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information - = note: `#[deny(invalid_doc_attributes)]` on by default - -error: aborting due to 1 previous error; 1 warning emitted + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> +note: the lint level is defined here + --> $DIR/future-incompatible-lint-group.rs:3:9 + | +LL | #![deny(future_incompatible)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]` diff --git a/tests/ui/issues/issue-16048.stderr b/tests/ui/issues/issue-16048.stderr index 73610942d7a..f97f13152bc 100644 --- a/tests/ui/issues/issue-16048.stderr +++ b/tests/ui/issues/issue-16048.stderr @@ -11,9 +11,13 @@ error[E0605]: non-primitive cast: `Foo<'a>` as `T` --> $DIR/issue-16048.rs:24:16 | LL | return *self as T; - | ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)` + | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - return *self as T; +LL + return T::from(*self); | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-17441.stderr b/tests/ui/issues/issue-17441.stderr index 29e50b91c7c..96aad879e24 100644 --- a/tests/ui/issues/issue-17441.stderr +++ b/tests/ui/issues/issue-17441.stderr @@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]` --> $DIR/issue-17441.rs:2:16 | LL | let _foo = &[1_usize, 2] as [usize]; - | ^^^^^^^^^^^^^^^^^------- - | | - | help: try casting to a reference instead: `&[usize]` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider casting to a reference instead + | +LL | let _foo = &[1_usize, 2] as &[usize]; + | + error[E0620]: cast to unsized type: `Box<usize>` as `dyn Debug` --> $DIR/issue-17441.rs:5:16 | LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^^------------------- - | | - | help: you can cast to a `Box` instead: `Box<dyn std::fmt::Debug>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: you can cast to a `Box` instead + | +LL | let _bar = Box::new(1_usize) as Box<dyn std::fmt::Debug>; + | ++++ + error[E0620]: cast to unsized type: `usize` as `dyn Debug` --> $DIR/issue-17441.rs:8:16 diff --git a/tests/ui/lint/force-warn/ice-free.rs b/tests/ui/lint/force-warn/ice-free.rs new file mode 100644 index 00000000000..99b79f44648 --- /dev/null +++ b/tests/ui/lint/force-warn/ice-free.rs @@ -0,0 +1,9 @@ +//@ compile-flags: --force-warn pub_use_of_private_extern_crate +//@ check-pass + +extern crate core; +pub use core as reexported_core; +//~^ warning: extern crate `core` is private +//~| warning: this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/lint/force-warn/ice-free.stderr b/tests/ui/lint/force-warn/ice-free.stderr new file mode 100644 index 00000000000..b64e3b138a2 --- /dev/null +++ b/tests/ui/lint/force-warn/ice-free.stderr @@ -0,0 +1,32 @@ +warning[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/ice-free.rs:5:9 + | +LL | pub use core as reexported_core; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909> + = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate` +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0365`. +Future incompatibility report: Future breakage diagnostic: +warning[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/ice-free.rs:5:9 + | +LL | pub use core as reexported_core; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909> + = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate` +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + diff --git a/tests/ui/lint/implicit_autorefs.fixed b/tests/ui/lint/implicit_autorefs.fixed index 454dfe76372..7aa21e77458 100644 --- a/tests/ui/lint/implicit_autorefs.fixed +++ b/tests/ui/lint/implicit_autorefs.fixed @@ -1,4 +1,4 @@ -//@ check-pass +//@ check-fail //@ run-rustfix #![allow(dead_code)] // For the rustfix-ed code. @@ -8,7 +8,7 @@ use std::ops::Deref; unsafe fn test_const(ptr: *const [u8]) { let _ = (&(*ptr))[..16]; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } struct Test { @@ -17,36 +17,36 @@ struct Test { unsafe fn test_field(ptr: *const Test) -> *const [u8] { let l = (&(*ptr).field).len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref &raw const (&(*ptr).field)[..l - 1] - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_builtin_index(a: *mut [String]) { _ = (&(*a)[0]).len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref _ = (&(&(*a))[..1][0]).len(); - //~^ WARN implicit autoref - //~^^ WARN implicit autoref + //~^ ERROR implicit autoref + //~^^ ERROR implicit autoref } unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) { let _ = (&(*ptr)).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = &raw const (&(*ptr)).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) { let _ = (&(*ptr)).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) { let _ = (&(*ptr)).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_manually_overloaded_deref() { @@ -54,52 +54,55 @@ unsafe fn test_manually_overloaded_deref() { impl<T> Deref for W<T> { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } } let w: W<i32> = W(5); let w = &raw const w; let _p: *const i32 = &raw const *(&**w); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } struct Test2 { // Derefs to `[u8]`. - field: &'static [u8] + field: &'static [u8], } fn test_more_manual_deref(ptr: *const Test2) -> usize { unsafe { (&(*ptr).field).len() } - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) { - ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not - // annotated with `#[rustc_no_implicit_auto_ref]` + // Should not warn, as `ManuallyDrop::write` is not + // annotated with `#[rustc_no_implicit_auto_ref]` + ptr.write(ManuallyDrop::new(1)); } unsafe fn test_vec_get(ptr: *mut Vec<u8>) { let _ = (&(*ptr)).get(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (&(*ptr)).get_unchecked(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (&mut (*ptr)).get_mut(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (&mut (*ptr)).get_unchecked_mut(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_string(ptr: *mut String) { let _ = (&(*ptr)).len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (&(*ptr)).is_empty(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) { let _ = (&(&(*slice))[..]).len(); - //~^ WARN implicit autoref - //~^^ WARN implicit autoref + //~^ ERROR implicit autoref + //~^^ ERROR implicit autoref } fn main() {} diff --git a/tests/ui/lint/implicit_autorefs.rs b/tests/ui/lint/implicit_autorefs.rs index 507d6536828..f33cb08e985 100644 --- a/tests/ui/lint/implicit_autorefs.rs +++ b/tests/ui/lint/implicit_autorefs.rs @@ -1,4 +1,4 @@ -//@ check-pass +//@ check-fail //@ run-rustfix #![allow(dead_code)] // For the rustfix-ed code. @@ -8,7 +8,7 @@ use std::ops::Deref; unsafe fn test_const(ptr: *const [u8]) { let _ = (*ptr)[..16]; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } struct Test { @@ -17,36 +17,36 @@ struct Test { unsafe fn test_field(ptr: *const Test) -> *const [u8] { let l = (*ptr).field.len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref &raw const (*ptr).field[..l - 1] - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_builtin_index(a: *mut [String]) { _ = (*a)[0].len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref _ = (*a)[..1][0].len(); - //~^ WARN implicit autoref - //~^^ WARN implicit autoref + //~^ ERROR implicit autoref + //~^^ ERROR implicit autoref } unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) { let _ = (*ptr).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = &raw const (*ptr).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) { let _ = (*ptr).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) { let _ = (*ptr).field; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_manually_overloaded_deref() { @@ -54,52 +54,55 @@ unsafe fn test_manually_overloaded_deref() { impl<T> Deref for W<T> { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } } let w: W<i32> = W(5); let w = &raw const w; let _p: *const i32 = &raw const **w; - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } struct Test2 { // Derefs to `[u8]`. - field: &'static [u8] + field: &'static [u8], } fn test_more_manual_deref(ptr: *const Test2) -> usize { unsafe { (*ptr).field.len() } - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) { - ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not - // annotated with `#[rustc_no_implicit_auto_ref]` + // Should not warn, as `ManuallyDrop::write` is not + // annotated with `#[rustc_no_implicit_auto_ref]` + ptr.write(ManuallyDrop::new(1)); } unsafe fn test_vec_get(ptr: *mut Vec<u8>) { let _ = (*ptr).get(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (*ptr).get_unchecked(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (*ptr).get_mut(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (*ptr).get_unchecked_mut(0); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn test_string(ptr: *mut String) { let _ = (*ptr).len(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref let _ = (*ptr).is_empty(); - //~^ WARN implicit autoref + //~^ ERROR implicit autoref } unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) { let _ = (*slice)[..].len(); - //~^ WARN implicit autoref - //~^^ WARN implicit autoref + //~^ ERROR implicit autoref + //~^^ ERROR implicit autoref } fn main() {} diff --git a/tests/ui/lint/implicit_autorefs.stderr b/tests/ui/lint/implicit_autorefs.stderr index 80ba8ae2fd2..bd914e2998a 100644 --- a/tests/ui/lint/implicit_autorefs.stderr +++ b/tests/ui/lint/implicit_autorefs.stderr @@ -1,4 +1,4 @@ -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:10:13 | LL | let _ = (*ptr)[..16]; @@ -12,13 +12,13 @@ note: autoref is being applied to this expression, resulting in: `&[u8]` | LL | let _ = (*ptr)[..16]; | ^^^^^^ - = note: `#[warn(dangerous_implicit_autorefs)]` on by default + = note: `#[deny(dangerous_implicit_autorefs)]` on by default help: try using a raw pointer method instead; or if this reference is intentional, make it explicit | LL | let _ = (&(*ptr))[..16]; | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:19:13 | LL | let l = (*ptr).field.len(); @@ -39,7 +39,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let l = (&(*ptr).field).len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:22:16 | LL | &raw const (*ptr).field[..l - 1] @@ -58,7 +58,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | &raw const (&(*ptr).field)[..l - 1] | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:27:9 | LL | _ = (*a)[0].len(); @@ -79,7 +79,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | _ = (&(*a)[0]).len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:30:9 | LL | _ = (*a)[..1][0].len(); @@ -100,7 +100,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | _ = (&(*a)[..1][0]).len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:30:9 | LL | _ = (*a)[..1][0].len(); @@ -119,7 +119,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | _ = (&(*a))[..1][0].len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:36:13 | LL | let _ = (*ptr).field; @@ -134,7 +134,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).field; | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:38:24 | LL | let _ = &raw const (*ptr).field; @@ -149,7 +149,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = &raw const (&(*ptr)).field; | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:43:13 | LL | let _ = (*ptr).field; @@ -164,7 +164,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).field; | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer +error: implicit autoref creates a reference to the dereference of a raw pointer --> $DIR/implicit_autorefs.rs:48:13 | LL | let _ = (*ptr).field; @@ -179,8 +179,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).field; | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:62:26 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:64:26 | LL | let _p: *const i32 = &raw const **w; | ^^^^^^^^^^^^^- @@ -189,7 +189,7 @@ LL | let _p: *const i32 = &raw const **w; | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&W<i32>` - --> $DIR/implicit_autorefs.rs:62:38 + --> $DIR/implicit_autorefs.rs:64:38 | LL | let _p: *const i32 = &raw const **w; | ^^ @@ -198,8 +198,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _p: *const i32 = &raw const *(&**w); | +++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:72:14 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:74:14 | LL | unsafe { (*ptr).field.len() } | ^^---^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | unsafe { (*ptr).field.len() } | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&[u8]` - --> $DIR/implicit_autorefs.rs:72:14 + --> $DIR/implicit_autorefs.rs:74:14 | LL | unsafe { (*ptr).field.len() } | ^^^^^^^^^^^^ @@ -219,8 +219,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | unsafe { (&(*ptr).field).len() } | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:82:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:85:13 | LL | let _ = (*ptr).get(0); | ^^---^^^^^^^^ @@ -229,7 +229,7 @@ LL | let _ = (*ptr).get(0); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&[u8]` - --> $DIR/implicit_autorefs.rs:82:13 + --> $DIR/implicit_autorefs.rs:85:13 | LL | let _ = (*ptr).get(0); | ^^^^^^ @@ -240,8 +240,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).get(0); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:84:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:87:13 | LL | let _ = (*ptr).get_unchecked(0); | ^^---^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL | let _ = (*ptr).get_unchecked(0); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&[u8]` - --> $DIR/implicit_autorefs.rs:84:13 + --> $DIR/implicit_autorefs.rs:87:13 | LL | let _ = (*ptr).get_unchecked(0); | ^^^^^^ @@ -261,8 +261,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).get_unchecked(0); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:86:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:89:13 | LL | let _ = (*ptr).get_mut(0); | ^^---^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | let _ = (*ptr).get_mut(0); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&mut [u8]` - --> $DIR/implicit_autorefs.rs:86:13 + --> $DIR/implicit_autorefs.rs:89:13 | LL | let _ = (*ptr).get_mut(0); | ^^^^^^ @@ -282,8 +282,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&mut (*ptr)).get_mut(0); | +++++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:88:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:91:13 | LL | let _ = (*ptr).get_unchecked_mut(0); | ^^---^^^^^^^^^^^^^^^^^^^^^^ @@ -292,7 +292,7 @@ LL | let _ = (*ptr).get_unchecked_mut(0); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&mut [u8]` - --> $DIR/implicit_autorefs.rs:88:13 + --> $DIR/implicit_autorefs.rs:91:13 | LL | let _ = (*ptr).get_unchecked_mut(0); | ^^^^^^ @@ -303,8 +303,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&mut (*ptr)).get_unchecked_mut(0); | +++++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:93:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:96:13 | LL | let _ = (*ptr).len(); | ^^---^^^^^^^ @@ -313,7 +313,7 @@ LL | let _ = (*ptr).len(); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&String` - --> $DIR/implicit_autorefs.rs:93:13 + --> $DIR/implicit_autorefs.rs:96:13 | LL | let _ = (*ptr).len(); | ^^^^^^ @@ -324,8 +324,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:95:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:98:13 | LL | let _ = (*ptr).is_empty(); | ^^---^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL | let _ = (*ptr).is_empty(); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&String` - --> $DIR/implicit_autorefs.rs:95:13 + --> $DIR/implicit_autorefs.rs:98:13 | LL | let _ = (*ptr).is_empty(); | ^^^^^^ @@ -345,8 +345,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*ptr)).is_empty(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:100:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:103:13 | LL | let _ = (*slice)[..].len(); | ^^-----^^^^^^^^^^^ @@ -355,7 +355,7 @@ LL | let _ = (*slice)[..].len(); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&[T]` - --> $DIR/implicit_autorefs.rs:100:13 + --> $DIR/implicit_autorefs.rs:103:13 | LL | let _ = (*slice)[..].len(); | ^^^^^^^^^^^^ @@ -366,8 +366,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*slice)[..]).len(); | ++ + -warning: implicit autoref creates a reference to the dereference of a raw pointer - --> $DIR/implicit_autorefs.rs:100:13 +error: implicit autoref creates a reference to the dereference of a raw pointer + --> $DIR/implicit_autorefs.rs:103:13 | LL | let _ = (*slice)[..].len(); | ^^-----^^^^^ @@ -376,7 +376,7 @@ LL | let _ = (*slice)[..].len(); | = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements note: autoref is being applied to this expression, resulting in: `&[T]` - --> $DIR/implicit_autorefs.rs:100:13 + --> $DIR/implicit_autorefs.rs:103:13 | LL | let _ = (*slice)[..].len(); | ^^^^^^^^ @@ -385,5 +385,5 @@ help: try using a raw pointer method instead; or if this reference is intentiona LL | let _ = (&(*slice))[..].len(); | ++ + -warning: 20 warnings emitted +error: aborting due to 20 previous errors diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs index 4ec52f20747..898665278e3 100644 --- a/tests/ui/lint/unused/useless-comment.rs +++ b/tests/ui/lint/unused/useless-comment.rs @@ -9,8 +9,13 @@ macro_rules! mac { /// foo //~ ERROR unused doc comment mac!(); +/// a //~ ERROR unused doc comment +#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment +unsafe extern "C" { } + fn foo() { /// a //~ ERROR unused doc comment + #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment let x = 12; /// multi-line //~ ERROR unused doc comment @@ -19,6 +24,7 @@ fn foo() { match x { /// c //~ ERROR unused doc comment 1 => {}, + #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment _ => {} } @@ -32,6 +38,7 @@ fn foo() { /// bar //~ ERROR unused doc comment mac!(); + #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment let x = /** comment */ 47; //~ ERROR unused doc comment /// dox //~ ERROR unused doc comment diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr index 8bb5bdaeb25..39873b82b75 100644 --- a/tests/ui/lint/unused/useless-comment.stderr +++ b/tests/ui/lint/unused/useless-comment.stderr @@ -12,7 +12,28 @@ LL | #![deny(unused_doc_comments)] | ^^^^^^^^^^^^^^^^^^^ error: unused doc comment - --> $DIR/useless-comment.rs:32:5 + --> $DIR/useless-comment.rs:12:1 + | +LL | /// a + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[doc(test(attr(allow(dead_code))))] +LL | unsafe extern "C" { } + | --------------------- rustdoc does not generate documentation for extern blocks + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:13:1 + | +LL | #[doc(test(attr(allow(dead_code))))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe extern "C" { } + | --------------------- rustdoc does not generate documentation for extern blocks + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:38:5 | LL | /// bar | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations @@ -20,17 +41,28 @@ LL | /// bar = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion error: unused doc comment - --> $DIR/useless-comment.rs:13:5 + --> $DIR/useless-comment.rs:17:5 | LL | /// a | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[doc(test(attr(allow(dead_code))))] LL | let x = 12; | ----------- rustdoc does not generate documentation for statements | = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:16:5 + --> $DIR/useless-comment.rs:18:5 + | +LL | #[doc(test(attr(allow(dead_code))))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:21:5 | LL | / /// multi-line LL | | /// doc comment @@ -39,6 +71,7 @@ LL | | /// that is unused LL | / match x { LL | | /// c LL | | 1 => {}, +LL | | #[doc(test(attr(allow(dead_code))))] LL | | _ => {} LL | | } | |_____- rustdoc does not generate documentation for expressions @@ -46,7 +79,7 @@ LL | | } = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:20:9 + --> $DIR/useless-comment.rs:25:9 | LL | /// c | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +89,17 @@ LL | 1 => {}, = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:25:5 + --> $DIR/useless-comment.rs:27:9 + | +LL | #[doc(test(attr(allow(dead_code))))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | _ => {} + | ------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:31:5 | LL | /// foo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +109,7 @@ LL | unsafe {} = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:28:5 + --> $DIR/useless-comment.rs:34:5 | LL | #[doc = "foo"] | ^^^^^^^^^^^^^^ @@ -77,7 +120,7 @@ LL | 3; = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:29:5 + --> $DIR/useless-comment.rs:35:5 | LL | #[doc = "bar"] | ^^^^^^^^^^^^^^ @@ -87,7 +130,17 @@ LL | 3; = help: use `//` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:35:13 + --> $DIR/useless-comment.rs:41:5 + | +LL | #[doc(test(attr(allow(dead_code))))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = /** comment */ 47; + | -------------------------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:42:13 | LL | let x = /** comment */ 47; | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions @@ -95,7 +148,7 @@ LL | let x = /** comment */ 47; = help: use `/* */` for a plain comment error: unused doc comment - --> $DIR/useless-comment.rs:37:5 + --> $DIR/useless-comment.rs:44:5 | LL | /// dox | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,5 +159,5 @@ LL | | } | = help: use `//` for a plain comment -error: aborting due to 10 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index a4276395944..a188b7791fd 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -104,10 +104,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/cast-rfc0401.rs:41:13 | LL | let _ = 0x61u32 as char; - | ^^^^^^^^^^^^^^^ - | | - | invalid cast - | help: try `char::from_u32` instead: `char::from_u32(0x61u32)` + | ^^^^^^^^^^^^^^^ invalid cast + | +help: consider using `char::from_u32` instead + | +LL - let _ = 0x61u32 as char; +LL + let _ = char::from_u32(0x61u32); + | error[E0606]: casting `bool` as `f32` is invalid --> $DIR/cast-rfc0401.rs:43:13 diff --git a/tests/ui/nonscalar-cast.stderr b/tests/ui/nonscalar-cast.stderr index 01b4a9a7ce0..834d4ea241c 100644 --- a/tests/ui/nonscalar-cast.stderr +++ b/tests/ui/nonscalar-cast.stderr @@ -2,9 +2,13 @@ error[E0605]: non-primitive cast: `Foo` as `isize` --> $DIR/nonscalar-cast.rs:15:20 | LL | println!("{}", Foo { x: 1 } as isize); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })` + | ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - println!("{}", Foo { x: 1 } as isize); +LL + println!("{}", isize::from(Foo { x: 1 })); | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error: aborting due to 1 previous error diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr index d974f5add50..1c862f2b606 100644 --- a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr +++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr @@ -2,12 +2,13 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/copy-check-when-count-inferred-later.rs:8:14 | LL | let a = [String::new(); _]; - | ^^^^^^^^^^^^^ - | | - | the trait `Copy` is not implemented for `String` - | help: create an inline `const` block: `const { String::new() }` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because this value will be copied for each element of the array +help: create an inline `const` block + | +LL | let a = [const { String::new() }; _]; + | +++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-test-attr-pass.rs b/tests/ui/rustdoc/doc-test-attr-pass.rs index f0120b7c2d0..60d1e3722bd 100644 --- a/tests/ui/rustdoc/doc-test-attr-pass.rs +++ b/tests/ui/rustdoc/doc-test-attr-pass.rs @@ -6,4 +6,46 @@ #![doc(test(attr(deny(warnings))))] #![doc(test())] +mod test { + #![doc(test(attr(allow(warnings))))] +} + +#[doc(test(attr(allow(dead_code))))] +static S: u32 = 5; + +#[doc(test(attr(allow(dead_code))))] +const C: u32 = 5; + +#[doc(test(attr(deny(dead_code))))] +struct A { + #[doc(test(attr(allow(dead_code))))] + field: u32 +} + +#[doc(test(attr(deny(dead_code))))] +union U { + #[doc(test(attr(allow(dead_code))))] + field: u32, + field2: u64, +} + +#[doc(test(attr(deny(dead_code))))] +enum Enum { + #[doc(test(attr(allow(dead_code))))] + Variant1, +} + +#[doc(test(attr(deny(dead_code))))] +impl A { + #[doc(test(attr(deny(dead_code))))] + fn method() {} +} + +#[doc(test(attr(deny(dead_code))))] +trait MyTrait { + #[doc(test(attr(deny(dead_code))))] + fn my_trait_fn(); +} + +#[doc(test(attr(deny(dead_code))))] pub fn foo() {} diff --git a/tests/crashes/140571.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index 97fa1d8432d..f4cde1d62b2 100644 --- a/tests/crashes/140571.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -1,14 +1,21 @@ -//@ known-bug: #140571 +// Regression test for #140571. The compiler used to ICE + +#![feature(associated_const_equality, specialization)] +//~^ WARN the feature `specialization` is incomplete + pub trait IsVoid { const IS_VOID: bool; } impl<T> IsVoid for T { default const IS_VOID: bool = false; } -impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} pub trait NotVoid {} impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {} pub trait Maybe<T> {} impl<T> Maybe<T> for T {} +impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} +//~^ ERROR conflicting implementations of trait `Maybe<()>` for type `()` + +fn main() {} diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr new file mode 100644 index 00000000000..a26b30fbb63 --- /dev/null +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:39 + | +LL | #![feature(associated_const_equality, specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()` + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1 + | +LL | impl<T> Maybe<T> for T {} + | ---------------------- first implementation here +LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr index 2e1dde27d0f..8ec1c5f11ec 100644 --- a/tests/ui/tag-variant-cast-non-nullary.stderr +++ b/tests/ui/tag-variant-cast-non-nullary.stderr @@ -2,10 +2,14 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize` --> $DIR/tag-variant-cast-non-nullary.rs:19:15 | LL | let val = v as isize; - | ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)` + | ^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less | - = note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information +help: consider using the `From` trait instead + | +LL - let val = v as isize; +LL + let val = isize::from(v); + | error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr index 7c09ab6a91a..72a253c4be8 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>` --> $DIR/constrain_in_projection2.rs:28:14 | LL | let x = <Foo as Trait<Bar>>::Assoc::default(); - | ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc` + | ^^^ | note: multiple `impl`s satisfying `Foo: Trait<Bar>` found --> $DIR/constrain_in_projection2.rs:18:1 @@ -13,6 +13,11 @@ LL | impl Trait<()> for Foo { LL | impl Trait<u32> for Foo { | ^^^^^^^^^^^^^^^^^^^^^^^ = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` +help: use the fully qualified path to an implementation + | +LL - let x = <Foo as Trait<Bar>>::Assoc::default(); +LL + let x = <<Type as Trait>::Assoc as Trait<Bar>>::Assoc::default(); + | error: aborting due to 1 previous error |
