diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 8556e8288670f..ff389607457d4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -757,9 +757,11 @@ macro_rules! common_visitor_and_walkers { ) -> V::Result; } - // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier + // This is only used by the MutVisitor. We include this symmetry here to make writing other + // functions easier. $(${ignore($lt)} - #[expect(unused, rustc::pass_by_value)] + #[cfg_attr(not(bootstrap), expect(unused, rustc::disallowed_pass_by_ref))] + #[cfg_attr(bootstrap, expect(unused, rustc::pass_by_value))] #[inline] )? fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 24a7215ddb385..ee21f0df5e217 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2521,16 +2521,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Block(block, _) => { if let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind - && matches!( - expr.kind, - ExprKind::Block(..) - | ExprKind::Path(..) - | ExprKind::Struct(..) - | ExprKind::Call(..) - | ExprKind::Tup(..) - | ExprKind::Array(..) - | ExprKind::ConstBlock(..) - ) { return self.lower_expr_to_const_arg_direct(expr); } @@ -2553,6 +2543,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = expr.span; let literal = self.lower_lit(literal, span); + if !matches!(literal.node, LitKind::Int(..)) { + let err = + self.dcx().struct_span_err(expr.span, "negated literal must be an integer"); + + return ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Error(err.emit()), + span, + }; + } + ConstArg { hir_id: self.lower_node_id(expr.id), kind: hir::ConstArgKind::Literal { lit: literal.node, negated: true }, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index d9b82e97cb462..650e6262b35e8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -26,15 +26,14 @@ pub(crate) fn expand_deriving_eq( additional_bounds: Vec::new(), supports_unions: true, methods: vec![MethodDef { - name: sym::assert_receiver_is_total_eq, + name: sym::assert_fields_are_eq, generics: Bounds::empty(), explicit_self: true, nonself_args: vec![], ret_ty: Unit, attributes: thin_vec![ - cx.attr_word(sym::inline, span), cx.attr_nested_word(sym::doc, sym::hidden, span), - cx.attr_nested_word(sym::coverage, sym::off, span) + cx.attr_nested_word(sym::coverage, sym::off, span), ], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index e1937f5c11eb5..f65da57317ce0 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1655,6 +1655,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { unimplemented!(); } + fn get_funclet_cleanuppad(&self, _funclet: &Funclet) -> RValue<'gcc> { + unimplemented!(); + } + // Atomic Operations fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 4ffc836f5559c..16c9d557d6b65 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1296,6 +1296,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ret } + fn get_funclet_cleanuppad(&self, funclet: &Funclet<'ll>) -> &'ll Value { + funclet.cleanuppad() + } + // Atomic Operations fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 388503c720532..27634cd9142ae 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -22,6 +22,7 @@ use rustc_errors::DiagCtxtHandle; use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::attrs::NativeLibKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::Diagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{ @@ -60,7 +61,8 @@ use super::rpath::{self, RPathConfig}; use super::{apple, versioned_llvm_target}; use crate::base::needs_allocator_shim_for_linking; use crate::{ - CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file, + CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, + looks_like_rust_object_file, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -670,6 +672,147 @@ struct LinkerOutput { inner: String, } +fn is_msvc_link_exe(sess: &Session) -> bool { + let (linker_path, flavor) = linker_and_flavor(sess); + sess.target.is_like_msvc + && flavor == LinkerFlavor::Msvc(Lld::No) + // Match exactly "link.exe" + && linker_path.to_str() == Some("link.exe") +} + +fn is_macos_ld(sess: &Session) -> bool { + let (_, flavor) = linker_and_flavor(sess); + sess.target.is_like_darwin && matches!(flavor, LinkerFlavor::Darwin(_, Lld::No)) +} + +fn is_windows_gnu_ld(sess: &Session) -> bool { + let (_, flavor) = linker_and_flavor(sess); + sess.target.is_like_windows + && !sess.target.is_like_msvc + && matches!(flavor, LinkerFlavor::Gnu(_, Lld::No)) +} + +fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8], stderr: &[u8]) { + let mut escaped_stderr = escape_string(&stderr); + let mut escaped_stdout = escape_string(&stdout); + let mut linker_info = String::new(); + + info!("linker stderr:\n{}", &escaped_stderr); + info!("linker stdout:\n{}", &escaped_stdout); + + fn for_each(bytes: &[u8], mut f: impl FnMut(&str, &mut String)) -> String { + let mut output = String::new(); + if let Ok(str) = str::from_utf8(bytes) { + info!("line: {str}"); + output = String::with_capacity(str.len()); + for line in str.lines() { + f(line.trim(), &mut output); + } + } + escape_string(output.trim().as_bytes()) + } + + if is_msvc_link_exe(sess) { + info!("inferred MSVC link.exe"); + + escaped_stdout = for_each(&stdout, |line, output| { + // Hide some progress messages from link.exe that we don't care about. + // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 + if line.starts_with(" Creating library") + || line.starts_with("Generating code") + || line.starts_with("Finished generating code") + { + linker_info += line; + linker_info += "\r\n"; + } else { + *output += line; + *output += "\r\n" + } + }); + } else if is_macos_ld(sess) { + info!("inferred macOS LD"); + + // FIXME: Tracked by https://github.com/rust-lang/rust/issues/136113 + let deployment_mismatch = |line: &str| { + line.starts_with("ld: warning: object file (") + && line.contains("was built for newer 'macOS' version") + && line.contains("than being linked") + }; + // FIXME: This is a real warning we would like to show, but it hits too many crates + // to want to turn it on immediately. + let search_path = |line: &str| { + line.starts_with("ld: warning: search path '") && line.ends_with("' not found") + }; + escaped_stderr = for_each(&stderr, |line, output| { + // This duplicate library warning is just not helpful at all. + if line.starts_with("ld: warning: ignoring duplicate libraries: ") + || deployment_mismatch(line) + || search_path(line) + { + linker_info += line; + linker_info += "\n"; + } else { + *output += line; + *output += "\n" + } + }); + } else if is_windows_gnu_ld(sess) { + info!("inferred Windows GNU LD"); + + let mut saw_exclude_symbol = false; + // See https://github.com/rust-lang/rust/issues/112368. + // FIXME: maybe check that binutils is older than 2.40 before downgrading this warning? + let exclude_symbols = |line: &str| { + line.starts_with("Warning: .drectve `-exclude-symbols:") + && line.ends_with("' unrecognized") + }; + escaped_stderr = for_each(&stderr, |line, output| { + if exclude_symbols(line) { + saw_exclude_symbol = true; + linker_info += line; + linker_info += "\n"; + } else if saw_exclude_symbol && line == "Warning: corrupt .drectve at end of def file" { + linker_info += line; + linker_info += "\n"; + } else { + *output += line; + *output += "\n" + } + }); + } + + let lint_msg = |msg| { + diag_lint_level( + sess, + LINKER_MESSAGES, + levels.linker_messages, + None, + LinkerOutput { inner: msg }, + ); + }; + let lint_info = |msg| { + diag_lint_level(sess, LINKER_INFO, levels.linker_info, None, LinkerOutput { inner: msg }); + }; + + if !escaped_stderr.is_empty() { + // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. + escaped_stderr = + escaped_stderr.strip_prefix("warning: ").unwrap_or(&escaped_stderr).to_owned(); + // Windows GNU LD prints uppercase Warning + escaped_stderr = escaped_stderr + .strip_prefix("Warning: ") + .unwrap_or(&escaped_stderr) + .replace(": warning: ", ": "); + lint_msg(format!("linker stderr: {escaped_stderr}")); + } + if !escaped_stdout.is_empty() { + lint_msg(format!("linker stdout: {}", escaped_stdout)) + } + if !linker_info.is_empty() { + lint_info(linker_info); + } +} + /// Create a dynamic library or executable. /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream @@ -856,11 +999,6 @@ fn link_natively( match prog { Ok(prog) => { - let is_msvc_link_exe = sess.target.is_like_msvc - && flavor == LinkerFlavor::Msvc(Lld::No) - // Match exactly "link.exe" - && linker_path.to_str() == Some("link.exe"); - if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); @@ -880,7 +1018,7 @@ fn link_natively( if let Some(code) = prog.status.code() { // All Microsoft `link.exe` linking ror codes are // four digit numbers in the range 1000 to 9999 inclusive - if is_msvc_link_exe && (code < 1000 || code > 9999) { + if is_msvc_link_exe(sess) && (code < 1000 || code > 9999) { let is_vs_installed = find_msvc_tools::find_vs_version().is_ok(); let has_linker = find_msvc_tools::find_tool(sess.target.arch.desc(), "link.exe") @@ -912,46 +1050,13 @@ fn link_natively( sess.dcx().abort_if_errors(); } - let stderr = escape_string(&prog.stderr); - let mut stdout = escape_string(&prog.stdout); - info!("linker stderr:\n{}", &stderr); - info!("linker stdout:\n{}", &stdout); - - // Hide some progress messages from link.exe that we don't care about. - // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 - if is_msvc_link_exe { - if let Ok(str) = str::from_utf8(&prog.stdout) { - let mut output = String::with_capacity(str.len()); - for line in stdout.lines() { - if line.starts_with(" Creating library") - || line.starts_with("Generating code") - || line.starts_with("Finished generating code") - { - continue; - } - output += line; - output += "\r\n" - } - stdout = escape_string(output.trim().as_bytes()) - } - } - - let level = codegen_results.crate_info.lint_levels.linker_messages; - let lint = |msg| { - diag_lint_level(sess, LINKER_MESSAGES, level, None, LinkerOutput { inner: msg }); - }; - - if !prog.stderr.is_empty() { - // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. - let stderr = stderr - .strip_prefix("warning: ") - .unwrap_or(&stderr) - .replace(": warning: ", ": "); - lint(format!("linker stderr: {stderr}")); - } - if !stdout.is_empty() { - lint(format!("linker stdout: {}", stdout)) - } + info!("reporting linker output: flavor={flavor:?}"); + report_linker_output( + sess, + codegen_results.crate_info.lint_levels, + &prog.stdout, + &prog.stderr, + ); } Err(e) => { let linker_not_found = e.kind() == io::ErrorKind::NotFound; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c7e90d3b3c330..6ef2447715ffa 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -24,6 +24,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; use rustc_hir::attrs::{CfgEntry, NativeLibKind, WindowsSubsystemKind}; use rustc_hir::def_id::CrateNum; +use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; @@ -361,10 +362,14 @@ impl CodegenResults { #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevels { linker_messages: LevelAndSource, + linker_info: LevelAndSource, } impl CodegenLintLevels { pub fn from_tcx(tcx: TyCtxt<'_>) -> Self { - Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) } + Self { + linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID), + linker_info: tcx.lint_level_at_node(LINKER_INFO, CRATE_HIR_ID), + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 35de8b5e1486b..4859380daa662 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -215,19 +215,18 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, mir::UnwindAction::Terminate(reason) => { - if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) { + if fx.mir[self.bb].is_cleanup && base::wants_wasm_eh(fx.cx.tcx().sess) { + // For wasm, we need to generate a nested `cleanuppad within %outer_pad` + // to catch exceptions during cleanup and call `panic_in_cleanup`. + Some(fx.terminate_block(reason, Some(self.bb))) + } else if fx.mir[self.bb].is_cleanup + && base::wants_new_eh_instructions(fx.cx.tcx().sess) + { // MSVC SEH will abort automatically if an exception tries to // propagate out from cleanup. - - // FIXME(@mirkootter): For wasm, we currently do not support terminate during - // cleanup, because this requires a few more changes: The current code - // caches the `terminate_block` for each function; funclet based code - however - - // requires a different terminate_block for each funclet - // Until this is implemented, we just do not unwind inside cleanup blocks - None } else { - Some(fx.terminate_block(reason)) + Some(fx.terminate_block(reason, None)) } } }; @@ -239,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if let Some(unwind_block) = unwind_block { let ret_llbb = if let Some((_, target)) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -310,7 +309,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { let unwind_target = match unwind { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), - mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)), + mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason, None)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, }; @@ -318,7 +317,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) { assert!(unwind_target.is_none()); let ret_llbb = if let Some(target) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -335,7 +334,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { MergingSucc::False } else if let Some(cleanup) = unwind_target { let ret_llbb = if let Some(target) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -1830,8 +1829,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { - if let Some((cached_bb, cached_reason)) = self.terminate_block + fn terminate_block( + &mut self, + reason: UnwindTerminateReason, + outer_catchpad_bb: Option, + ) -> Bx::BasicBlock { + // mb_funclet_bb should be present if and only if the target is wasm and + // we're terminating because of an unwind in a cleanup block. In that + // case we have nested funclets and the inner catch_switch needs to know + // what outer catch_pad it is contained in. + debug_assert!( + outer_catchpad_bb.is_some() + == (base::wants_wasm_eh(self.cx.tcx().sess) + && reason == UnwindTerminateReason::InCleanup) + ); + + // When we aren't in a wasm InCleanup block, there's only one terminate + // block needed so we cache at START_BLOCK index. + let mut cache_bb = mir::START_BLOCK; + // In wasm eh InCleanup, use the outer funclet's cleanup BB as the cache + // key. + if let Some(outer_bb) = outer_catchpad_bb { + let cleanup_kinds = + self.cleanup_kinds.as_ref().expect("cleanup_kinds required for funclets"); + cache_bb = cleanup_kinds[outer_bb] + .funclet_bb(outer_bb) + .expect("funclet_bb should be in a funclet"); + + // Ensure the outer funclet is created first + if self.funclets[cache_bb].is_none() { + self.landing_pad_for(cache_bb); + } + } + if let Some((cached_bb, cached_reason)) = self.terminate_blocks[cache_bb] && reason == cached_reason { return cached_bb; @@ -1869,12 +1899,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // cp_terminate: // %cp = catchpad within %cs [null, i32 64, null] // ... + // + // By contrast, on WebAssembly targets, we specifically _do_ want to + // catch foreign exceptions. The situation with MSVC is a + // regrettable hack which we don't want to extend to other targets + // unless necessary. For WebAssembly, to generate catch(...) and + // catch only C++ exception instead of generating a catch_all, we + // need to call the intrinsics @llvm.wasm.get.exception and + // @llvm.wasm.get.ehselector in the catch pad. Since we don't do + // this, we generate a catch_all. We originally got this behavior + // by accident but it luckily matches our intention. llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); - let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); let mut cs_bx = Bx::build(self.cx, llbb); - let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); + + // For wasm InCleanup blocks, our catch_switch is nested within the + // outer catchpad, so we need to provide it as the parent value to + // catch_switch. + let mut outer_cleanuppad = None; + if outer_catchpad_bb.is_some() { + // Get the outer funclet's catchpad + let outer_funclet = self.funclets[cache_bb] + .as_ref() + .expect("landing_pad_for didn't create funclet"); + outer_cleanuppad = Some(cs_bx.get_funclet_cleanuppad(outer_funclet)); + } + let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); + let cs = cs_bx.catch_switch(outer_cleanuppad, None, &[cp_llbb]); + drop(cs_bx); bx = Bx::build(self.cx, cp_llbb); let null = @@ -1895,13 +1948,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { // Specifying more arguments than necessary usually doesn't // hurt, but the `WasmEHPrepare` LLVM pass does not recognize - // anything other than a single `null` as a `catch (...)` block, + // anything other than a single `null` as a `catch_all` block, // leading to problems down the line during instruction // selection. &[null] as &[_] }; funclet = Some(bx.catch_pad(cs, args)); + // On wasm, if we wanted to generate a catch(...) and only catch C++ + // exceptions, we'd call @llvm.wasm.get.exception and + // @llvm.wasm.get.ehselector selectors here. We want a catch_all so + // we leave them out. This is intentionally diverging from the MSVC + // behavior. } else { llbb = Bx::append_block(self.cx, self.llfn, "terminate"); bx = Bx::build(self.cx, llbb); @@ -1927,7 +1985,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.unreachable(); - self.terminate_block = Some((llbb, reason)); + self.terminate_blocks[cache_bb] = Some((llbb, reason)); llbb } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 819abb9ae644d..1a0f66d31cca4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -90,8 +90,11 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option, - /// Cached terminate upon unwinding block and its reason - terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>, + /// Cached terminate upon unwinding block and its reason. For non-wasm + /// targets, there is at most one such block per function, stored at index + /// `START_BLOCK`. For wasm targets, each funclet needs its own terminate + /// block, indexed by the cleanup block that is the funclet's head. + terminate_blocks: IndexVec>, /// A bool flag for each basic block indicating whether it is a cold block. /// A cold block is a block that is unlikely to be executed at runtime. @@ -227,7 +230,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, - terminate_block: None, + terminate_blocks: IndexVec::from_elem(None, &mir.basic_blocks), cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 3486bd140eceb..edabd8188a3b6 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -552,12 +552,12 @@ pub trait BuilderMethods<'a, 'tcx>: fn set_personality_fn(&mut self, personality: Self::Function); - // These are used by everyone except msvc + // These are used by everyone except msvc and wasm EH fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value); fn filter_landing_pad(&mut self, pers_fn: Self::Function); fn resume(&mut self, exn0: Self::Value, exn1: Self::Value); - // These are used only by msvc + // These are used by msvc and wasm EH fn cleanup_pad(&mut self, parent: Option, args: &[Self::Value]) -> Self::Funclet; fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option); fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet; @@ -567,6 +567,7 @@ pub trait BuilderMethods<'a, 'tcx>: unwind: Option, handlers: &[Self::BasicBlock], ) -> Self::Value; + fn get_funclet_cleanuppad(&self, funclet: &Self::Funclet) -> Self::Value; fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 22636959f0db5..e0590263737cb 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -24,12 +24,11 @@ use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, LintDiagnostic, msg}; use rustc_feature::GateIssue; -use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, DocAttribute}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; -use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr}; use rustc_middle::bug; use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; @@ -59,7 +58,7 @@ use crate::lints::{ BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, - BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, + BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; declare_lint! { @@ -3184,3 +3183,62 @@ impl EarlyLintPass for SpecialModuleName { } } } + +declare_lint! { + /// The `internal_eq_trait_method_impls` lint detects manual + /// implementations of `Eq::assert_receiver_is_total_eq`. + /// + /// ### Example + /// + /// ```rust + /// #[derive(PartialEq)] + /// pub struct Foo; + /// + /// impl Eq for Foo { + /// fn assert_receiver_is_total_eq(&self) {} + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This method existed so that `#[derive(Eq)]` could check that all + /// fields of a type implement `Eq`. Other users were never supposed + /// to implement it and it was hidden from documentation. + /// + /// Unfortunately, it was not explicitly marked as unstable and some + /// people have now mistakenly assumed they had to implement this method. + /// + /// As the method is never called by the standard library, you can safely + /// remove any implementations of the method and just write `impl Eq for Foo {}`. + /// + /// This is a [future-incompatible] lint to transition this to a hard + /// error in the future. See [issue #152336] for more details. + /// + /// [issue #152336]: https://github.com/rust-lang/rust/issues/152336 + pub INTERNAL_EQ_TRAIT_METHOD_IMPLS, + Warn, + "manual implementation of the internal `Eq::assert_receiver_is_total_eq` method", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #152336), + report_in_deps: false, + }; +} + +declare_lint_pass!(InternalEqTraitMethodImpls => [INTERNAL_EQ_TRAIT_METHOD_IMPLS]); + +impl<'tcx> LateLintPass<'tcx> for InternalEqTraitMethodImpls { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::ImplItem<'tcx>) { + if let ImplItemImplKind::Trait { defaultness: _, trait_item_def_id: Ok(trait_item_def_id) } = + item.impl_kind + && cx.tcx.is_diagnostic_item(sym::assert_receiver_is_total_eq, trait_item_def_id) + { + cx.emit_span_lint( + INTERNAL_EQ_TRAIT_METHOD_IMPLS, + item.span, + EqInternalMethodImplemented, + ); + } + } +} diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs similarity index 75% rename from compiler/rustc_lint/src/pass_by_value.rs rename to compiler/rustc_lint/src/disallowed_pass_by_ref.rs index 5a4eb29433815..2a572a5a76bdb 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs @@ -3,34 +3,34 @@ use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind, f use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::lints::PassByValueDiag; +use crate::lints::DisallowedPassByRefDiag; use crate::{LateContext, LateLintPass, LintContext}; declare_tool_lint! { - /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to - /// always be passed by value. This is usually used for types that are thin wrappers around - /// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which - /// is a reference to an `Interned`) - pub rustc::PASS_BY_VALUE, + /// The `disallowed_pass_by_ref` lint detects if types marked with `#[rustc_pass_by_value]` are + /// passed by reference. Types with this marker are usually thin wrappers around references, so + /// there is no benefit to an extra layer of indirection. (Example: `Ty` which is a reference + /// to an `Interned`) + pub rustc::DISALLOWED_PASS_BY_REF, Warn, "pass by reference of a type flagged as `#[rustc_pass_by_value]`", report_in_external_macro: true } -declare_lint_pass!(PassByValue => [PASS_BY_VALUE]); +declare_lint_pass!(DisallowedPassByRef => [DISALLOWED_PASS_BY_REF]); -impl<'tcx> LateLintPass<'tcx> for PassByValue { +impl<'tcx> LateLintPass<'tcx> for DisallowedPassByRef { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match &ty.kind { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if cx.tcx.trait_impl_of_assoc(ty.hir_id.owner.to_def_id()).is_some() { return; } - if let Some(t) = path_for_pass_by_value(cx, inner_ty) { + if let Some(t) = path_for_rustc_pass_by_value(cx, inner_ty) { cx.emit_span_lint( - PASS_BY_VALUE, + DISALLOWED_PASS_BY_REF, ty.span, - PassByValueDiag { ty: t, suggestion: ty.span }, + DisallowedPassByRefDiag { ty: t, suggestion: ty.span }, ); } } @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { } } -fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option { +fn path_for_rustc_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option { if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind { match path.res { Res::Def(_, def_id) if find_attr!(cx.tcx, def_id, RustcPassByValue(_)) => { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index cd0d8765dd933..34276eb76cf39 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -37,6 +37,7 @@ mod context; mod dangling; mod default_could_be_derived; mod deref_into_dyn_supertrait; +mod disallowed_pass_by_ref; mod drop_forget_useless; mod early; mod enum_intrinsics_non_enums; @@ -65,7 +66,6 @@ mod non_local_def; mod nonstandard_style; mod noop_method_call; mod opaque_hidden_inferred_bound; -mod pass_by_value; mod passes; mod precedence; mod ptr_nulls; @@ -88,6 +88,7 @@ use builtin::*; use dangling::*; use default_could_be_derived::DefaultCouldBeDerived; use deref_into_dyn_supertrait::*; +use disallowed_pass_by_ref::*; use drop_forget_useless::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use for_loops_over_fallibles::*; @@ -109,7 +110,6 @@ use non_local_def::*; use nonstandard_style::*; use noop_method_call::*; use opaque_hidden_inferred_bound::*; -use pass_by_value::*; use precedence::*; use ptr_nulls::*; use redundant_semicolon::*; @@ -250,6 +250,7 @@ late_lint_methods!( FunctionCastsAsInteger: FunctionCastsAsInteger, CheckTransmutes: CheckTransmutes, LifetimeSyntax: LifetimeSyntax, + InternalEqTraitMethodImpls: InternalEqTraitMethodImpls, ] ] ); @@ -658,8 +659,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(TypeIr)); store.register_lints(&BadOptAccess::lint_vec()); store.register_late_mod_pass(|_| Box::new(BadOptAccess)); - store.register_lints(&PassByValue::lint_vec()); - store.register_late_mod_pass(|_| Box::new(PassByValue)); + store.register_lints(&DisallowedPassByRef::lint_vec()); + store.register_late_mod_pass(|_| Box::new(DisallowedPassByRef)); store.register_lints(&SpanUseEqCtxt::lint_vec()); store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt)); store.register_lints(&SymbolInternStringLiteral::lint_vec()); @@ -677,7 +678,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(POTENTIAL_QUERY_INSTABILITY), LintId::of(UNTRACKED_QUERY_INFORMATION), LintId::of(USAGE_OF_TY_TYKIND), - LintId::of(PASS_BY_VALUE), + LintId::of(DISALLOWED_PASS_BY_REF), LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT), diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 4b7e102e239ec..1d8f2d4e3442d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1807,10 +1807,10 @@ pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { pub end_span: Span, } -// pass_by_value.rs +// disallowed_pass_by_ref.rs #[derive(LintDiagnostic)] #[diag("passing `{$ty}` by reference")] -pub(crate) struct PassByValueDiag { +pub(crate) struct DisallowedPassByRefDiag { pub ty: String, #[suggestion("try passing by value", code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, @@ -3932,3 +3932,8 @@ pub(crate) struct MalformedOnConstAttrLint { #[label("invalid option found here")] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] +#[note("this method was used to add checks to the `Eq` derive macro")] +pub(crate) struct EqInternalMethodImplemented; diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index f2d621c2ad5ed..f37cf4c8dc8c0 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -151,7 +151,6 @@ pub fn is_ty_must_use<'tcx>( cx: &LateContext<'tcx>, ty: Ty<'tcx>, expr: &hir::Expr<'_>, - span: Span, simplify_uninhabited: bool, ) -> IsTyMustUse { if ty.is_unit() { @@ -165,12 +164,12 @@ pub fn is_ty_must_use<'tcx>( match *ty.kind() { _ if is_uninhabited(ty) => IsTyMustUse::Trivial, ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => { - is_ty_must_use(cx, boxed, expr, span, simplify_uninhabited) + is_ty_must_use(cx, boxed, expr, simplify_uninhabited) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => { let pinned_ty = args.type_at(0); - is_ty_must_use(cx, pinned_ty, expr, span, simplify_uninhabited) + is_ty_must_use(cx, pinned_ty, expr, simplify_uninhabited) .map(|inner| MustUsePath::Pinned(Box::new(inner))) } // Consider `Result` (e.g. `Result<(), !>`) equivalent to `T`. @@ -180,7 +179,7 @@ pub fn is_ty_must_use<'tcx>( && is_uninhabited(args.type_at(1)) => { let ok_ty = args.type_at(0); - is_ty_must_use(cx, ok_ty, expr, span, simplify_uninhabited) + is_ty_must_use(cx, ok_ty, expr, simplify_uninhabited) .map(|path| MustUsePath::Result(Box::new(path))) } // Consider `ControlFlow` (e.g. `ControlFlow`) equivalent to `T`. @@ -190,7 +189,7 @@ pub fn is_ty_must_use<'tcx>( && is_uninhabited(args.type_at(0)) => { let continue_ty = args.type_at(1); - is_ty_must_use(cx, continue_ty, expr, span, simplify_uninhabited) + is_ty_must_use(cx, continue_ty, expr, simplify_uninhabited) .map(|path| MustUsePath::ControlFlow(Box::new(path))) } // Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`). @@ -210,7 +209,7 @@ pub fn is_ty_must_use<'tcx>( IsTyMustUse::Trivial } ty::Adt(def, _) => { - is_def_must_use(cx, def.did(), span).map_or(IsTyMustUse::No, IsTyMustUse::Yes) + is_def_must_use(cx, def.did(), expr.span).map_or(IsTyMustUse::No, IsTyMustUse::Yes) } ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied()) @@ -223,7 +222,7 @@ pub fn is_ty_must_use<'tcx>( { let def_id = poly_trait_predicate.trait_ref.def_id; - is_def_must_use(cx, def_id, span) + is_def_must_use(cx, def_id, expr.span) } else { None } @@ -236,7 +235,7 @@ pub fn is_ty_must_use<'tcx>( .find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { let def_id = trait_ref.def_id; - is_def_must_use(cx, def_id, span) + is_def_must_use(cx, def_id, expr.span) .map(|inner| MustUsePath::TraitObject(Box::new(inner))) } else { None @@ -260,9 +259,7 @@ pub fn is_ty_must_use<'tcx>( .zip(elem_exprs) .enumerate() .filter_map(|(i, (ty, expr))| { - is_ty_must_use(cx, ty, expr, expr.span, simplify_uninhabited) - .yes() - .map(|path| (i, path)) + is_ty_must_use(cx, ty, expr, simplify_uninhabited).yes().map(|path| (i, path)) }) .collect::>(); @@ -276,21 +273,23 @@ pub fn is_ty_must_use<'tcx>( // If the array is empty we don't lint, to avoid false positives Some(0) | None => IsTyMustUse::No, // If the array is definitely non-empty, we can do `#[must_use]` checking. - Some(len) => is_ty_must_use(cx, ty, expr, span, simplify_uninhabited) + Some(len) => is_ty_must_use(cx, ty, expr, simplify_uninhabited) .map(|inner| MustUsePath::Array(Box::new(inner), len)), }, - ty::Closure(..) | ty::CoroutineClosure(..) => IsTyMustUse::Yes(MustUsePath::Closure(span)), + ty::Closure(..) | ty::CoroutineClosure(..) => { + IsTyMustUse::Yes(MustUsePath::Closure(expr.span)) + } ty::Coroutine(def_id, ..) => { // async fn should be treated as "implementor of `Future`" if cx.tcx.coroutine_is_async(def_id) && let Some(def_id) = cx.tcx.lang_items().future_trait() { IsTyMustUse::Yes(MustUsePath::Opaque(Box::new( - is_def_must_use(cx, def_id, span) + is_def_must_use(cx, def_id, expr.span) .expect("future trait is marked as `#[must_use]`"), ))) } else { - IsTyMustUse::Yes(MustUsePath::Coroutine(span)) + IsTyMustUse::Yes(MustUsePath::Coroutine(expr.span)) } } _ => IsTyMustUse::No, @@ -339,7 +338,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let ty = cx.typeck_results().expr_ty(expr); - let must_use_result = is_ty_must_use(cx, ty, expr, expr.span, false); + let must_use_result = is_ty_must_use(cx, ty, expr, false); let type_lint_emitted_or_trivial = match must_use_result { IsTyMustUse::Yes(path) => { emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c20c9dca346fd..35cc16bc0fc73 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -61,6 +61,7 @@ declare_lint_pass! { LARGE_ASSIGNMENTS, LATE_BOUND_LIFETIME_ARGUMENTS, LEGACY_DERIVE_HELPERS, + LINKER_INFO, LINKER_MESSAGES, LONG_RUNNING_CONST_EVAL, LOSSY_PROVENANCE_CASTS, @@ -4067,6 +4068,40 @@ declare_lint! { "warnings emitted at runtime by the target-specific linker program" } +declare_lint! { + /// The `linker_info` lint forwards warnings from the linker that are known to be informational-only. + /// + /// ### Example + /// + /// ```rust,ignore (needs CLI args, platform-specific) + /// #[warn(linker_info)] + /// fn main () {} + /// ``` + /// + /// On MacOS, using `-C link-arg=-lc` and the default linker, this will produce + /// + /// ```text + /// warning: linker stderr: ld: ignoring duplicate libraries: '-lc' + /// | + /// note: the lint level is defined here + /// --> ex.rs:1:9 + /// | + /// 1 | #![warn(linker_info)] + /// | ^^^^^^^^^^^^^^^ + /// ``` + /// + /// ### Explanation + /// + /// Many linkers are very "chatty" and print lots of information that is not necessarily + /// indicative of an issue. This output has been ignored for many years and is often not + /// actionable by developers. It is silenced unless the developer specifically requests for it + /// to be printed. See this tracking issue for more details: + /// . + pub LINKER_INFO, + Allow, + "linker warnings known to be informational-only and not indicative of a problem" +} + declare_lint! { /// The `named_arguments_used_positionally` lint detects cases where named arguments are only /// used positionally in format strings. This usage is valid but potentially very confusing. diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index ebfcb50e9cde5..cd9c53134ae20 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -293,12 +293,10 @@ fn make_helpers_for_query(query: &Query, streams: &mut HelperTokenStreams) { // Generate a function to check whether we should cache the query to disk, for some key. if let Some(CacheOnDiskIf { block, .. }) = modifiers.cache_on_disk_if.as_ref() { - // `pass_by_value`: some keys are marked with `rustc_pass_by_value`, but we take keys by - // reference here. - // FIXME: `pass_by_value` is badly named; `allow(rustc::pass_by_value)` actually means - // "allow pass by reference of `rustc_pass_by_value` types". + // `disallowed_pass_by_ref` is needed because some keys are `rustc_pass_by_value`. streams.cache_on_disk_if_fns_stream.extend(quote! { - #[allow(unused_variables, rustc::pass_by_value)] + #[cfg_attr(not(bootstrap), allow(unused_variables, rustc::disallowed_pass_by_ref))] + #[cfg_attr(bootstrap, allow(unused_variables, rustc::pass_by_value))] #[inline] pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, #key_pat: &#key_ty) -> bool #block diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index c926604a41952..0ddcdac817b80 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -9,6 +9,7 @@ use rustc_span::def_id::{CrateNum, LocalDefId}; use rustc_span::{ExpnHash, ExpnId}; use crate::mir; +use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex}; use crate::ty::{Ty, TyCtxt}; macro_rules! declare_hooks { @@ -107,6 +108,13 @@ declare_hooks! { /// /// Creates the MIR for a given `DefId`, including unreachable code. hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>; + + hook try_mark_green(dep_node: &crate::dep_graph::DepNode) -> bool; + + hook encode_all_query_results( + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex + ) -> (); } #[cold] diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index e874e7e22b5c9..8db48fc2f9956 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -1,6 +1,6 @@ use std::collections::hash_map::Entry; -use std::mem; use std::sync::Arc; +use std::{fmt, mem}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; @@ -261,7 +261,7 @@ impl OnDiskCache { tcx.sess.time("encode_query_results", || { let enc = &mut encoder; let qri = &mut query_result_index; - (tcx.query_system.fns.encode_query_results)(tcx, enc, qri); + tcx.encode_all_query_results(enc, qri); }); // Encode side effects. @@ -508,7 +508,7 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { // tag matches and the correct amount of bytes was read. fn decode_tagged(decoder: &mut D, expected_tag: T) -> V where - T: Decodable + Eq + std::fmt::Debug, + T: Decodable + Eq + fmt::Debug, V: Decodable, D: Decoder, { @@ -829,6 +829,13 @@ pub struct CacheEncoder<'a, 'tcx> { symbol_index_table: FxHashMap, } +impl<'a, 'tcx> fmt::Debug for CacheEncoder<'a, 'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Add more details here if/when necessary. + f.write_str("CacheEncoder") + } +} + impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { #[inline] fn source_file_index(&mut self, source_file: Arc) -> SourceFileIndex { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 9141f49bd45de..c2d524d200dee 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -11,11 +11,10 @@ use rustc_macros::HashStable; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; -use crate::dep_graph; use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables}; -use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; +use crate::query::on_disk_cache::OnDiskCache; use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; use crate::query::{QueryCache, QueryInfo, QueryJob}; use crate::ty::TyCtxt; @@ -216,17 +215,6 @@ impl<'tcx, C: QueryCache> QueryVTable<'tcx, C> { } } -pub struct QuerySystemFns { - pub local_providers: Providers, - pub extern_providers: ExternProviders, - pub encode_query_results: for<'tcx> fn( - tcx: TyCtxt<'tcx>, - encoder: &mut CacheEncoder<'_, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex, - ), - pub try_mark_green: for<'tcx> fn(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool, -} - pub struct QuerySystem<'tcx> { pub arenas: WorkerLocal>, pub query_vtables: QueryVTables<'tcx>, @@ -237,7 +225,8 @@ pub struct QuerySystem<'tcx> { /// This is `None` if we are not incremental compilation mode pub on_disk_cache: Option, - pub fns: QuerySystemFns, + pub local_providers: Providers, + pub extern_providers: ExternProviders, pub jobs: AtomicU64, } @@ -327,10 +316,6 @@ impl<'tcx> TyCtxt<'tcx> { pub fn at(self, span: Span) -> TyCtxtAt<'tcx> { TyCtxtAt { tcx: self, span } } - - pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool { - (self.query_system.fns.try_mark_green)(self, dep_node) - } } macro_rules! query_helper_param_ty { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index dd8491b00cee9..0960859fb2a4f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -302,7 +302,8 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { /// Insert a `(Value, Ty)` pair to be deduplicated. /// Returns `true` as second tuple field if this value did not exist previously. - #[allow(rustc::pass_by_value)] // closures take `&VnIndex` + #[cfg_attr(not(bootstrap), allow(rustc::disallowed_pass_by_ref))] // closures take `&VnIndex` + #[cfg_attr(bootstrap, allow(rustc::pass_by_value))] fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>) -> (VnIndex, bool) { debug_assert!(match value { Value::Opaque(_) | Value::Address { .. } => false, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 52dcade91aeaf..44e8f13dd2364 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1628,8 +1628,7 @@ impl<'a> Parser<'a> { let first_expr = self.parse_expr()?; if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` - let count = - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + let count = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?; self.expect(close)?; ExprKind::Repeat(first_expr, count) } else if self.eat(exp!(Comma)) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 69610d062919d..2ca4fac7fc46b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1587,9 +1587,7 @@ impl<'a> Parser<'a> { let rhs = match (self.eat(exp!(Eq)), const_arg) { (true, true) => ConstItemRhsKind::TypeConst { - rhs: Some( - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?, - ), + rhs: Some(self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?), }, (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) }, (false, true) => ConstItemRhsKind::TypeConst { rhs: None }, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 9196d8d156d8e..e514a08c8fb3a 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -915,28 +915,7 @@ impl<'a> Parser<'a> { }); } - let mgca_disambiguation = self.mgca_direct_lit_hack(&expr); - Ok((expr, mgca_disambiguation)) - } - - /// Under `min_generic_const_args` we still allow *some* anon consts to be written without - /// a `const` block as it makes things quite a lot nicer. This function is useful for contexts - /// where we would like to use `MgcaDisambiguation::Direct` but need to fudge it to be `AnonConst` - /// in the presence of literals. - // - /// FIXME(min_generic_const_args): In the long term it would be nice to have a way to directly - /// represent literals in `hir::ConstArgKind` so that we can remove this special case by not - /// needing an anon const. - pub fn mgca_direct_lit_hack(&self, expr: &Expr) -> MgcaDisambiguation { - match &expr.kind { - ast::ExprKind::Lit(_) => MgcaDisambiguation::AnonConst, - ast::ExprKind::Unary(ast::UnOp::Neg, expr) - if matches!(expr.kind, ast::ExprKind::Lit(_)) => - { - MgcaDisambiguation::AnonConst - } - _ => MgcaDisambiguation::Direct, - } + Ok((expr, MgcaDisambiguation::Direct)) } /// Parse a generic argument in a path segment. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6ff165eb22b71..40335ef1b1bc7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -658,8 +658,7 @@ impl<'a> Parser<'a> { }; let ty = if self.eat(exp!(Semi)) { - let mut length = - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + let mut length = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?; if let Err(e) = self.expect(exp!(CloseBracket)) { // Try to recover from `X` when `X::` works diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 89bd39b77e64b..ceae73727461b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1630,7 +1630,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::expect, ]) && let Some(meta) = attr.meta_item_list() && meta.iter().any(|meta| { - meta.meta_item().map_or(false, |item| item.path == sym::linker_messages) + meta.meta_item().map_or(false, |item| { + item.path == sym::linker_messages || item.path == sym::linker_info + }) }) { if hir_id != CRATE_HIR_ID { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index b9ada150d0301..bdd5373488b18 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -318,7 +318,7 @@ pub(crate) enum UnusedNote { #[note("`default_method_body_is_const` has been replaced with `const` on traits")] DefaultMethodBodyConst, #[note( - "the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked" + "the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked" )] LinkerMessagesBinaryCrateOnly, } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 890c0b2ef92c7..afb41f69b5ebb 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sync::AtomicU64; use rustc_middle::dep_graph; use rustc_middle::queries::{self, ExternProviders, Providers}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; +use rustc_middle::query::plumbing::{QuerySystem, QueryVTable}; use rustc_middle::query::{AsLocalKey, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -59,12 +59,8 @@ pub fn query_system<'tcx>( arenas: Default::default(), query_vtables: make_query_vtables(incremental), on_disk_cache, - fns: QuerySystemFns { - local_providers, - extern_providers, - encode_query_results: encode_all_query_results, - try_mark_green, - }, + local_providers, + extern_providers, jobs: AtomicU64::new(1), } } @@ -74,4 +70,6 @@ rustc_middle::rustc_with_all_queries! { define_queries! } pub fn provide(providers: &mut rustc_middle::util::Providers) { providers.hooks.alloc_self_profile_query_strings = alloc_self_profile_query_strings; providers.hooks.query_key_hash_verify_all = query_key_hash_verify_all; + providers.hooks.encode_all_query_results = encode_all_query_results; + providers.hooks.try_mark_green = try_mark_green; } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 7b5fd76c31958..275fe5b63d8b0 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -226,13 +226,13 @@ macro_rules! hash_result { macro_rules! call_provider { ([][$tcx:expr, $name:ident, $key:expr]) => {{ - ($tcx.query_system.fns.local_providers.$name)($tcx, $key) + ($tcx.query_system.local_providers.$name)($tcx, $key) }}; ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{ if let Some(key) = $key.as_local_key() { - ($tcx.query_system.fns.local_providers.$name)($tcx, key) + ($tcx.query_system.local_providers.$name)($tcx, key) } else { - ($tcx.query_system.fns.extern_providers.$name)($tcx, $key) + ($tcx.query_system.extern_providers.$name)($tcx, $key) } }}; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3d40b7317459b..cdcad2c635902 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -432,6 +432,7 @@ symbols! { assert, assert_eq, assert_eq_macro, + assert_fields_are_eq, assert_inhabited, assert_macro, assert_mem_uninitialized_valid, @@ -1089,6 +1090,7 @@ symbols! { integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, internal, + internal_eq_trait_method_impls, internal_features, into_async_iter_into_iter, into_future, @@ -1151,6 +1153,7 @@ symbols! { link_section, linkage, linker, + linker_info, linker_messages, linkonce, linkonce_odr, diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 1d83799d7dab1..683b615eec83b 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -5,7 +5,7 @@ use rustc_abi::{Endian, HasDataLayout, TyAbiInterface}; use crate::callconv::{Align, ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::spec::{Abi, HasTargetSpec, Os}; +use crate::spec::{HasTargetSpec, Os}; #[derive(Debug, Clone, Copy, PartialEq)] enum ABI { @@ -106,9 +106,9 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let abi = if cx.target_spec().options.abi == Abi::ElfV2 { + let abi = if cx.target_spec().options.llvm_abiname == "elfv2" { ELFv2 - } else if cx.target_spec().options.abi == Abi::ElfV1 { + } else if cx.target_spec().options.llvm_abiname == "elfv1" { ELFv1 } else if cx.target_spec().os == Os::Aix { AIX diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 78ea1f1113258..b3dc435dda176 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -336,16 +336,24 @@ pub macro PartialEq($item:item) { #[rustc_diagnostic_item = "Eq"] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] pub const trait Eq: [const] PartialEq + PointeeSized { - // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a - // type implements `Eq` itself. The current deriving infrastructure means doing this assertion - // without using a method on this trait is nearly impossible. + // This method was used solely by `#[derive(Eq)]` to assert that every component of a + // type implements `Eq` itself. // // This should never be implemented by hand. #[doc(hidden)] #[coverage(off)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "assert_receiver_is_total_eq"] + #[deprecated(since = "1.95.0", note = "implementation detail of `#[derive(Eq)]`")] fn assert_receiver_is_total_eq(&self) {} + + // FIXME (#152504): this method is used solely by `#[derive(Eq)]` to assert that + // every component of a type implements `Eq` itself. It will be removed again soon. + #[doc(hidden)] + #[coverage(off)] + #[unstable(feature = "derive_eq_internals", issue = "none")] + fn assert_fields_are_eq(&self) {} } /// Derive macro generating an impl of the trait [`Eq`]. diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 0c607cb6ba6f3..f826ccd31e040 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -23,7 +23,7 @@ use crate::core::config::{Config, TargetSelection}; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; use crate::utils::exec::command; use crate::utils::helpers::{ - self, exe, get_clang_cl_resource_dir, libdir, t, unhashed_basename, up_to_date, + self, exe, get_clang_cl_resource_dir, t, unhashed_basename, up_to_date, }; use crate::{CLang, GitRepo, Kind, trace}; @@ -561,6 +561,7 @@ impl Step for Llvm { } }; + // FIXME(ZuseZ4): Do we need that for Enzyme too? // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned // libLLVM.dylib will be built. However, llvm-config will still look // for a versioned path like libLLVM-14.dylib. Manually create a symbolic @@ -1166,7 +1167,7 @@ impl Step for Enzyme { let llvm_version_major = llvm::get_llvm_version_major(builder, &host_llvm_config); let lib_ext = std::env::consts::DLL_EXTENSION; let libenzyme = format!("libEnzyme-{llvm_version_major}"); - let build_dir = out_dir.join(libdir(target)); + let build_dir = out_dir.join("lib"); let dylib = build_dir.join(&libenzyme).with_extension(lib_ext); trace!("checking build stamp to see if we need to rebuild enzyme artifacts"); @@ -1204,16 +1205,7 @@ impl Step for Enzyme { // hard to spot more relevant issues. let mut cflags = CcFlags::default(); cflags.push_all("-Wno-deprecated"); - - // Logic copied from `configure_llvm` - // ThinLTO is only available when building with LLVM, enabling LLD is required. - // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin. - let mut ldflags = LdFlags::default(); - if builder.config.llvm_thin_lto && !target.contains("apple") { - ldflags.push_all("-fuse-ld=lld"); - } - - configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]); + configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), cflags, &[]); // Re-use the same flags as llvm to control the level of debug information // generated by Enzyme. diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile index 9691d4b099b3b..3abca36fe70db 100644 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -97,7 +97,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ ./build/$HOSTS/stage1-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \ - --host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap enzyme + --host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang ENV LIBCURL_NO_PKG_CONFIG 1 diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh index 46d34cd001a95..c78b76a53f44c 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh @@ -9,7 +9,6 @@ python3 ../x.py build --set rust.debug=true opt-dist --include-default-paths \ build-manifest \ bootstrap \ - enzyme \ rustc_codegen_gcc # Use GCC for building GCC components, as it seems to behave badly when built with Clang diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index c06c85513856b..88b6855784979 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -504,7 +504,7 @@ auto: - name: dist-aarch64-apple env: SCRIPT: >- - ./x.py dist bootstrap enzyme + ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin @@ -513,7 +513,6 @@ auto: --enable-sanitizers --enable-profiler --set rust.jemalloc - --set llvm.link-shared=true --set rust.lto=thin --set rust.codegen-units=1 # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else @@ -707,7 +706,7 @@ auto: # i686 has no dedicated job, build it here because this job is fast - name: dist-aarch64-llvm-mingw env: - SCRIPT: python x.py dist bootstrap enzyme --include-default-paths + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: >- --build=aarch64-pc-windows-gnullvm --target=aarch64-pc-windows-gnullvm,i686-pc-windows-gnullvm @@ -721,7 +720,7 @@ auto: - name: dist-x86_64-llvm-mingw env: - SCRIPT: python x.py dist bootstrap enzyme --include-default-paths + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-gnullvm --enable-full-tools diff --git a/src/doc/reference b/src/doc/reference index 442cbef910566..50a1075e879be 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 442cbef9105662887d5eae2882ca551f3726bf28 +Subproject commit 50a1075e879be75aeec436252c84eef0fad489f4 diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index c16cfbe899b7b..c6061e78fd22a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -215,6 +215,7 @@ fn check_unexpected_extension(check: &mut RunningCheck, file_path: &Path, ext: & "fixed", // expected source file after applying fixes "md", // test directory descriptions "ftl", // translation tests + "ps1", // powershell scripts, used for fake linkers on Windows ]; const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ diff --git a/tests/codegen-llvm/double_panic_wasm.rs b/tests/codegen-llvm/double_panic_wasm.rs new file mode 100644 index 0000000000000..1eafe60503809 --- /dev/null +++ b/tests/codegen-llvm/double_panic_wasm.rs @@ -0,0 +1,34 @@ +//@ compile-flags: -C panic=unwind -Copt-level=0 +//@ needs-unwind +//@ only-wasm32 + +#![crate_type = "lib"] + +// Test that `panic_in_cleanup` is called on webassembly targets when a panic +// occurs in a destructor during unwinding. + +extern "Rust" { + fn may_panic(); +} + +struct PanicOnDrop; + +impl Drop for PanicOnDrop { + fn drop(&mut self) { + unsafe { may_panic() } + } +} + +// CHECK-LABEL: @double_panic +// CHECK: invoke void @may_panic() +// CHECK: invoke void @{{.+}}drop_in_place{{.+}} +// CHECK: unwind label %[[TERMINATE:.*]] +// +// CHECK: [[TERMINATE]]: +// CHECK: call void @{{.*panic_in_cleanup}} +// CHECK: unreachable +#[no_mangle] +pub fn double_panic() { + let _guard = PanicOnDrop; + unsafe { may_panic() } +} diff --git a/tests/codegen-llvm/terminating-catchpad.rs b/tests/codegen-llvm/terminating-catchpad.rs index a2ec19871d1fc..7c98ea94fdc13 100644 --- a/tests/codegen-llvm/terminating-catchpad.rs +++ b/tests/codegen-llvm/terminating-catchpad.rs @@ -9,6 +9,10 @@ // Ensure a catch-all generates: // - `catchpad ... [ptr null]` on Wasm (otherwise LLVM gets confused) // - `catchpad ... [ptr null, i32 64, ptr null]` on Windows (otherwise we catch SEH exceptions) +// +// Unlike on windows, on Wasm, we specifically do want to catch foreign +// exceptions. To catch only C++ exceptions we'd need to call +// @llvm.wasm.get.exception and @llvm.wasm.get.ehselector in the catchpad. #![feature(no_core, lang_items, rustc_attrs)] #![crate_type = "lib"] @@ -36,8 +40,14 @@ fn panic_cannot_unwind() -> ! { #[no_mangle] #[rustc_nounwind] pub fn doesnt_unwind() { + // CHECK: catchswitch within none [label %{{.*}}] unwind to caller // emscripten: %catchpad = catchpad within %catchswitch [ptr null] // wasi: %catchpad = catchpad within %catchswitch [ptr null] // seh: %catchpad = catchpad within %catchswitch [ptr null, i32 64, ptr null] + // + // We don't call these intrinsics on wasm targets so we generate a catch_all + // instruction which also picks up foreign exceptions + // NOT: @llvm.wasm.get.exception + // NOT: @llvm.wasm.get.ehselector unwinds(); } diff --git a/tests/run-make/macos-deployment-target-warning/foo.c b/tests/run-make/macos-deployment-target-warning/foo.c new file mode 100644 index 0000000000000..85e6cd8c3909a --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/tests/run-make/macos-deployment-target-warning/main.rs b/tests/run-make/macos-deployment-target-warning/main.rs new file mode 100644 index 0000000000000..2c3be92812e12 --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/main.rs @@ -0,0 +1,8 @@ +#![warn(linker_info, linker_messages)] +unsafe extern "C" { + safe fn foo(); +} + +fn main() { + foo(); +} diff --git a/tests/run-make/macos-deployment-target-warning/rmake.rs b/tests/run-make/macos-deployment-target-warning/rmake.rs new file mode 100644 index 0000000000000..e109b2adcc17a --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/rmake.rs @@ -0,0 +1,29 @@ +//@ only-apple +//! Tests that deployment target linker warnings are shown as `linker-info`, not `linker-messages` + +use run_make_support::external_deps::c_cxx_compiler::cc; +use run_make_support::external_deps::llvm::llvm_ar; +use run_make_support::{bare_rustc, diff}; + +fn main() { + let cwd = std::env::current_dir().unwrap().to_str().unwrap().to_owned(); + + cc().arg("-c").arg("-mmacosx-version-min=15.5").output("foo.o").input("foo.c").run(); + llvm_ar().obj_to_ar().output_input("libfoo.a", "foo.o").run(); + + let warnings = bare_rustc() + .arg("-L") + .arg(format!("native={cwd}")) + .arg("-lstatic=foo") + .link_arg("-mmacosx-version-min=11.2") + .input("main.rs") + .crate_type("bin") + .run() + .stderr_utf8(); + + diff() + .expected_file("warnings.txt") + .actual_text("(rustc -W linker-info)", &warnings) + .normalize(r"\(.*/rmake_out/", "(TEST_DIR/") + .run() +} diff --git a/tests/run-make/macos-deployment-target-warning/warnings.txt b/tests/run-make/macos-deployment-target-warning/warnings.txt new file mode 100644 index 0000000000000..ab08c6d9ae5b2 --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/warnings.txt @@ -0,0 +1,11 @@ +warning: ld: warning: object file (TEST_DIR/libfoo.a[2](foo.o)) was built for newer 'macOS' version (15.5) than being linked (11.2) + + | +note: the lint level is defined here + --> main.rs:1:9 + | +1 | #![warn(linker_info, linker_messages)] + | ^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.rs b/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.rs index 06d2232be5179..42d75be966840 100644 --- a/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.rs +++ b/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.rs @@ -1,8 +1,8 @@ //@ compile-flags: -Z unstable-options - +//@ ignore-stage1 (this can be removed when nightly goes to 1.96) #![feature(rustc_attrs)] #![feature(rustc_private)] -#![deny(rustc::pass_by_value)] +#![deny(rustc::disallowed_pass_by_ref)] #![allow(unused)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr b/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr index 69cf20656d7b1..b2906ea1e1195 100644 --- a/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr +++ b/tests/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr @@ -7,8 +7,8 @@ LL | ty_ref: &Ty<'_>, note: the lint level is defined here --> $DIR/rustc_pass_by_value.rs:5:9 | -LL | #![deny(rustc::pass_by_value)] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rustc::disallowed_pass_by_ref)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: passing `TyCtxt<'_>` by reference --> $DIR/rustc_pass_by_value.rs:16:18 diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index cc08c25906b66..7443c2977d54d 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,27 +1,14 @@ -error[E0277]: the trait bound `FreshTy(0): A` is not satisfied +error: type annotations needed for the literal --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:32:33 | LL | let _: dyn A; - | ^ the trait `A` is not implemented for `FreshTy(0)` - | -help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 - | -LL | impl A for () { - | ^^^^^^^^^^^^^ + | ^ -error[E0277]: the trait bound `FreshTy(0): A` is not satisfied +error: type annotations needed for the literal --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:34 | LL | let _: &dyn A = &(); - | ^ the trait `A` is not implemented for `FreshTy(0)` - | -help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 - | -LL | impl A for () { - | ^^^^^^^^^^^^^ + | ^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/mgca/array-expr-complex.stderr b/tests/ui/const-generics/mgca/array-expr-complex.stderr index beac1aa232f2f..544b0f05b4e44 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.stderr @@ -5,16 +5,16 @@ LL | takes_array::<{ [1, 2, 1 + 2] }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:10:19 + --> $DIR/array-expr-complex.rs:10:21 | LL | takes_array::<{ [X; 3] }>(); - | ^^^^^^^^^^ + | ^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:12:19 + --> $DIR/array-expr-complex.rs:12:21 | LL | takes_array::<{ [0; Y] }>(); - | ^^^^^^^^^^ + | ^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index cda519b96d4d8..98feccfc99c74 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -14,7 +14,7 @@ where fn bar() where - T: Trait2<3>, //~ ERROR: mismatched types + T: Trait2<3>, //~ ERROR: type annotations needed for the literal { } diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr index be40e44742267..169282547fc1d 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr @@ -4,12 +4,11 @@ error: expected `usize`, found const array LL | T: Trait1<{ [] }>, | ^^ -error[E0308]: mismatched types +error: type annotations needed for the literal --> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15 | LL | T: Trait2<3>, - | ^ expected `[u8; 3]`, found integer + | ^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index 714d7a804d111..1c72afce52c7d 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:13:33 + --> $DIR/explicit_anon_consts.rs:13:35 | LL | type Adt4 = Foo<{ 1 + 1 }>; - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block --> $DIR/explicit_anon_consts.rs:21:34 @@ -17,22 +17,22 @@ LL | let _4 = [(); 1 + 1]; | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:45:43 + --> $DIR/explicit_anon_consts.rs:45:45 | LL | type const ITEM4: usize = { 1 + 1 }; - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:62:23 + --> $DIR/explicit_anon_consts.rs:62:25 | LL | T4: Trait, - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:71:50 + --> $DIR/explicit_anon_consts.rs:71:52 | LL | struct Default4; - | ^^^^^^^^^ + | ^^^^^ error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:42:51 diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index cd68a2c0d4301..4a3efb801cb01 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,4 +1,4 @@ -#![feature(adt_const_params, min_generic_const_args)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; @@ -10,17 +10,22 @@ struct Foo { fn foo() {} +fn bar() {} + fn main() { foo::<{ Foo { field: -1_usize } }>(); //~^ ERROR: type annotations needed for the literal foo::<{ Foo { field: { -1_usize } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR: type annotations needed for the literal foo::<{ Foo { field: -true } }>(); - //~^ ERROR: the constant `true` is not of type `isize` + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: { -true } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: -"<3" } }>(); - //~^ ERROR: the constant `"<3"` is not of type `isize` + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: { -"<3" } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR negated literal must be an integer + + bar::<{ -"hi" }>(); + //~^ ERROR: negated literal must be an integer } diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr index 43ed4b71e33e7..60c559d1d5ba9 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr @@ -1,38 +1,44 @@ -error: complex const arguments must be placed inside of a `const` block - --> $DIR/nonsensical-negated-literal.rs:16:26 +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:20:26 | -LL | foo::<{ Foo { field: { -1_usize } } }>(); - | ^^^^^^^^^^^^ +LL | foo::<{ Foo { field: -true } }>(); + | ^^^^^ -error: complex const arguments must be placed inside of a `const` block - --> $DIR/nonsensical-negated-literal.rs:20:26 +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:22:28 | LL | foo::<{ Foo { field: { -true } } }>(); - | ^^^^^^^^^ + | ^^^^^ -error: complex const arguments must be placed inside of a `const` block +error: negated literal must be an integer --> $DIR/nonsensical-negated-literal.rs:24:26 | +LL | foo::<{ Foo { field: -"<3" } }>(); + | ^^^^^ + +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:26:28 + | LL | foo::<{ Foo { field: { -"<3" } } }>(); - | ^^^^^^^^^ + | ^^^^^ + +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:29:13 + | +LL | bar::<{ -"hi" }>(); + | ^^^^^ error: type annotations needed for the literal - --> $DIR/nonsensical-negated-literal.rs:14:26 + --> $DIR/nonsensical-negated-literal.rs:16:26 | LL | foo::<{ Foo { field: -1_usize } }>(); | ^^^^^^^^ -error: the constant `true` is not of type `isize` - --> $DIR/nonsensical-negated-literal.rs:18:13 - | -LL | foo::<{ Foo { field: -true } }>(); - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` - -error: the constant `"<3"` is not of type `isize` - --> $DIR/nonsensical-negated-literal.rs:22:13 +error: type annotations needed for the literal + --> $DIR/nonsensical-negated-literal.rs:18:28 | -LL | foo::<{ Foo { field: -"<3" } }>(); - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&'static str` +LL | foo::<{ Foo { field: { -1_usize } } }>(); + | ^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs index 3262e79478bdb..c57121a4a26a0 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs @@ -6,6 +6,7 @@ struct A; impl A { type const B = 4; //~^ ERROR: missing type for `const` item + //~| ERROR: type annotations needed for the literal } fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr index 77e54ab2f2e93..7fbb7461a4911 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr @@ -9,5 +9,11 @@ help: provide a type for the item LL | type const B: = 4; | ++++++++ -error: aborting due to 1 previous error +error: type annotations needed for the literal + --> $DIR/type_const-inherent-const-omitted-type.rs:7:20 + | +LL | type const B = 4; + | ^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index c73785f9a3e38..b17a5b2b978a6 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -3,7 +3,6 @@ type const FREE: u32 = 5_usize; //~^ ERROR the constant `5` is not of type `u32` -//~| ERROR mismatched types type const FREE2: isize = FREE; //~^ ERROR the constant `5` is not of type `isize` @@ -14,7 +13,7 @@ trait Tr { impl Tr for () { type const N: usize = false; - //~^ ERROR mismatched types + //~^ ERROR the constant `false` is not of type `usize` } fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index f7f64c535f602..e2c916cf6d05a 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -5,29 +5,16 @@ LL | type const FREE: u32 = 5_usize; | ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` error: the constant `5` is not of type `isize` - --> $DIR/type_const-mismatched-types.rs:8:1 + --> $DIR/type_const-mismatched-types.rs:7:1 | LL | type const FREE2: isize = FREE; | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` -error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:16:27 +error: the constant `false` is not of type `usize` + --> $DIR/type_const-mismatched-types.rs:15:5 | LL | type const N: usize = false; - | ^^^^^ expected `usize`, found `bool` + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:4:24 - | -LL | type const FREE: u32 = 5_usize; - | ^^^^^^^ expected `u32`, found `usize` - | -help: change the type of the numeric literal from `usize` to `u32` - | -LL - type const FREE: u32 = 5_usize; -LL + type const FREE: u32 = 5_u32; - | - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs index a7ff9f0ce03f7..c8c7788eb135a 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs @@ -10,6 +10,7 @@ struct GoodS; impl BadTr for GoodS { type const NUM: = 84; //~^ ERROR: missing type for `const` item + //~| ERROR: type annotations needed for the literal } diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr index 11a60246f6a68..99dc6398170db 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr @@ -5,12 +5,18 @@ LL | type const NUM: = 84; | ^ help: provide a type for the associated constant: `usize` error: use of trait associated const not defined as `type const` - --> $DIR/type_const-only-in-impl-omitted-type.rs:16:43 + --> $DIR/type_const-only-in-impl-omitted-type.rs:17:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ | = note: the declaration in the trait must begin with `type const` not just `const` alone -error: aborting due to 2 previous errors +error: type annotations needed for the literal + --> $DIR/type_const-only-in-impl-omitted-type.rs:11:23 + | +LL | type const NUM: = 84; + | ^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 2a05d77f8f6da..19c8090e8de8b 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -62,10 +62,9 @@ impl ::core::cmp::PartialEq for Empty { } #[automatically_derived] impl ::core::cmp::Eq for Empty { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) {} + fn assert_fields_are_eq(&self) {} } #[automatically_derived] impl ::core::cmp::PartialOrd for Empty { @@ -139,10 +138,9 @@ impl ::core::cmp::PartialEq for Point { } #[automatically_derived] impl ::core::cmp::Eq for Point { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -227,10 +225,9 @@ impl ::core::cmp::PartialEq for PackedPoint { } #[automatically_derived] impl ::core::cmp::Eq for PackedPoint { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -310,10 +307,9 @@ impl ::core::cmp::PartialEq for TupleSingleField { } #[automatically_derived] impl ::core::cmp::Eq for TupleSingleField { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -385,10 +381,9 @@ impl ::core::cmp::PartialEq for SingleField { } #[automatically_derived] impl ::core::cmp::Eq for SingleField { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -490,10 +485,9 @@ impl ::core::cmp::PartialEq for Big { } #[automatically_derived] impl ::core::cmp::Eq for Big { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -754,10 +748,9 @@ impl ::core::cmp::PartialEq for Unsized { } #[automatically_derived] impl ::core::cmp::Eq for Unsized { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq<[u32]>; } } @@ -849,10 +842,9 @@ impl #[automatically_derived] impl ::core::cmp::Eq for Generic where T::A: ::core::cmp::Eq { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; @@ -971,10 +963,9 @@ impl ::core::cmp::Eq for PackedGeneric where T::A: ::core::cmp::Eq + ::core::marker::Copy { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; @@ -1056,10 +1047,9 @@ impl ::core::cmp::PartialEq for Enum0 { } #[automatically_derived] impl ::core::cmp::Eq for Enum0 { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) {} + fn assert_fields_are_eq(&self) {} } #[automatically_derived] impl ::core::cmp::PartialOrd for Enum0 { @@ -1126,10 +1116,9 @@ impl ::core::cmp::PartialEq for Enum1 { } #[automatically_derived] impl ::core::cmp::Eq for Enum1 { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; } } @@ -1192,10 +1181,9 @@ impl ::core::cmp::PartialEq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::Eq for Fieldless1 { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) {} + fn assert_fields_are_eq(&self) {} } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless1 { @@ -1269,10 +1257,9 @@ impl ::core::cmp::PartialEq for Fieldless { } #[automatically_derived] impl ::core::cmp::Eq for Fieldless { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) {} + fn assert_fields_are_eq(&self) {} } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless { @@ -1379,10 +1366,9 @@ impl ::core::cmp::PartialEq for Mixed { } #[automatically_derived] impl ::core::cmp::Eq for Mixed { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq>; let _: ::core::cmp::AssertParamIsEq>; @@ -1577,10 +1563,9 @@ impl ::core::cmp::PartialEq for Fielded { } #[automatically_derived] impl ::core::cmp::Eq for Fielded { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq>; @@ -1699,10 +1684,9 @@ impl #[automatically_derived] impl ::core::cmp::Eq for EnumGeneric { - #[inline] #[doc(hidden)] #[coverage(off)] - fn assert_receiver_is_total_eq(&self) { + fn assert_fields_are_eq(&self) { let _: ::core::cmp::AssertParamIsEq; let _: ::core::cmp::AssertParamIsEq; } diff --git a/tests/ui/deriving/internal_eq_trait_method_impls.rs b/tests/ui/deriving/internal_eq_trait_method_impls.rs new file mode 100644 index 0000000000000..b2605fe3c8668 --- /dev/null +++ b/tests/ui/deriving/internal_eq_trait_method_impls.rs @@ -0,0 +1,48 @@ +#![deny(deprecated, internal_eq_trait_method_impls)] +pub struct Bad; + +impl PartialEq for Bad { + fn eq(&self, _: &Self) -> bool { + true + } +} + +impl Eq for Bad { + fn assert_receiver_is_total_eq(&self) {} + //~^ ERROR: `Eq::assert_receiver_is_total_eq` should never be implemented by hand [internal_eq_trait_method_impls] + //~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +#[derive(PartialEq, Eq)] +pub struct Good; + +#[derive(PartialEq)] +pub struct Good2; + +impl Eq for Good2 {} + +pub struct Foo; + +pub trait SameName { + fn assert_receiver_is_total_eq(&self) {} +} + +impl SameName for Foo { + fn assert_receiver_is_total_eq(&self) {} +} + +pub fn main() { + Foo.assert_receiver_is_total_eq(); + Good2.assert_receiver_is_total_eq(); + //~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated] + Good.assert_receiver_is_total_eq(); + //~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated] + Bad.assert_receiver_is_total_eq(); + //~^ ERROR: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` [deprecated] +} + +#[forbid(internal_eq_trait_method_impls)] +mod forbid { + #[derive(PartialEq, Eq)] + pub struct Foo; +} diff --git a/tests/ui/deriving/internal_eq_trait_method_impls.stderr b/tests/ui/deriving/internal_eq_trait_method_impls.stderr new file mode 100644 index 0000000000000..8ff8fe337a78c --- /dev/null +++ b/tests/ui/deriving/internal_eq_trait_method_impls.stderr @@ -0,0 +1,41 @@ +error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` + --> $DIR/internal_eq_trait_method_impls.rs:36:11 + | +LL | Good2.assert_receiver_is_total_eq(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/internal_eq_trait_method_impls.rs:1:9 + | +LL | #![deny(deprecated, internal_eq_trait_method_impls)] + | ^^^^^^^^^^ + +error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` + --> $DIR/internal_eq_trait_method_impls.rs:38:10 + | +LL | Good.assert_receiver_is_total_eq(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated method `std::cmp::Eq::assert_receiver_is_total_eq`: implementation detail of `#[derive(Eq)]` + --> $DIR/internal_eq_trait_method_impls.rs:40:9 + | +LL | Bad.assert_receiver_is_total_eq(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `Eq::assert_receiver_is_total_eq` should never be implemented by hand + --> $DIR/internal_eq_trait_method_impls.rs:11:5 + | +LL | fn assert_receiver_is_total_eq(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #152336 + = note: this method was used to add checks to the `Eq` derive macro +note: the lint level is defined here + --> $DIR/internal_eq_trait_method_impls.rs:1:21 + | +LL | #![deny(deprecated, internal_eq_trait_method_impls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/internal-lints/rustc_pass_by_value_self.rs b/tests/ui/internal-lints/rustc_pass_by_value_self.rs index d2e0e272025f6..695c617d32f82 100644 --- a/tests/ui/internal-lints/rustc_pass_by_value_self.rs +++ b/tests/ui/internal-lints/rustc_pass_by_value_self.rs @@ -5,7 +5,7 @@ // Considering that all other `internal-lints` are tested here // this seems like the cleaner solution though. #![feature(rustc_attrs)] -#![deny(rustc::pass_by_value)] +#![deny(rustc::disallowed_pass_by_ref)] #![allow(unused)] #[rustc_pass_by_value] diff --git a/tests/ui/internal-lints/rustc_pass_by_value_self.stderr b/tests/ui/internal-lints/rustc_pass_by_value_self.stderr index fb39ed60b8235..d9e9f7e48506b 100644 --- a/tests/ui/internal-lints/rustc_pass_by_value_self.stderr +++ b/tests/ui/internal-lints/rustc_pass_by_value_self.stderr @@ -7,8 +7,8 @@ LL | fn by_ref(&self) {} note: the lint level is defined here --> $DIR/rustc_pass_by_value_self.rs:8:9 | -LL | #![deny(rustc::pass_by_value)] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rustc::disallowed_pass_by_ref)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: passing `Ty<'tcx>` by reference --> $DIR/rustc_pass_by_value_self.rs:30:21 diff --git a/tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs b/tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs index 62d352facd178..c292b8c02eca2 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs @@ -6,6 +6,8 @@ //@ ignore-backends: gcc #![allow(incomplete_features)] +// FIXME: "type and size of dynamic symbol are not defined" with GNU LD +#![allow(linker_messages)] #![feature(raw_dylib_elf)] #![no_std] #![no_main] diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs index 030b95198f545..22e5c57b9e1d2 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs @@ -17,6 +17,8 @@ #![feature(raw_dylib_elf)] #![allow(incomplete_features)] +// FIXME: "type and size of dynamic symbol are not defined" with GNU LD +#![allow(linker_messages)] #[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] #[cfg_attr(without, link(name = "rawdylibbutforcats"))] diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs index 20de4afcee0bc..327bc94d91fbb 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs @@ -16,6 +16,8 @@ #![feature(raw_dylib_elf)] #![allow(incomplete_features)] +// FIXME: "type and size of dynamic symbol are not defined" with GNU LD +#![allow(linker_messages)] #[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] #[cfg_attr(without, link(name = "rawdylibbutforcats"))] diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs index 302ec0edeaa18..12b0ec9b88985 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs @@ -17,6 +17,8 @@ #![feature(raw_dylib_elf)] #![allow(incomplete_features)] +// FIXME: "type and size of dynamic symbol are not defined" with GNU LD +#![allow(linker_messages)] #[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib", modifiers = "+verbatim"))] #[cfg_attr(without, link(name = "rawdylibbutforcats", modifiers = "+verbatim"))] diff --git a/tests/ui/linking/auxiliary/fake-linker.ps1 b/tests/ui/linking/auxiliary/fake-linker.ps1 new file mode 100755 index 0000000000000..59322c3205dae --- /dev/null +++ b/tests/ui/linking/auxiliary/fake-linker.ps1 @@ -0,0 +1,3 @@ +#!/usr/bin/env pwsh +[Console]::Error.WriteLine('Warning: .drectve `-exclude-symbols:_ZN28windows_gnu_corrupt_drective4main17h291ed884c1aada69E '' unrecognized') +[Console]::Error.WriteLine('Warning: corrupt .drectve at end of def file') diff --git a/tests/ui/linking/macos-ignoring-duplicate.rs b/tests/ui/linking/macos-ignoring-duplicate.rs new file mode 100644 index 0000000000000..0c9241c8ee195 --- /dev/null +++ b/tests/ui/linking/macos-ignoring-duplicate.rs @@ -0,0 +1,6 @@ +//@ only-apple +//@ compile-flags: -C link-arg=-lc -C link-arg=-lc +//@ build-fail +#![deny(linker_info)] +//~? ERROR ignoring duplicate libraries +fn main() {} diff --git a/tests/ui/linking/macos-ignoring-duplicate.stderr b/tests/ui/linking/macos-ignoring-duplicate.stderr new file mode 100644 index 0000000000000..9037e8f4e391b --- /dev/null +++ b/tests/ui/linking/macos-ignoring-duplicate.stderr @@ -0,0 +1,11 @@ +error: ld: warning: ignoring duplicate libraries: '-lc' + + | +note: the lint level is defined here + --> $DIR/macos-ignoring-duplicate.rs:4:9 + | +LL | #![deny(linker_info)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/linking/macos-search-path.rs b/tests/ui/linking/macos-search-path.rs new file mode 100644 index 0000000000000..6d3e420bcdf6d --- /dev/null +++ b/tests/ui/linking/macos-search-path.rs @@ -0,0 +1,6 @@ +//@ only-apple +//@ compile-flags: -C link-arg=-Wl,-L/no/such/file/or/directory +//@ build-fail +#![deny(linker_info)] +//~? ERROR search path +fn main() {} diff --git a/tests/ui/linking/macos-search-path.stderr b/tests/ui/linking/macos-search-path.stderr new file mode 100644 index 0000000000000..598036d0d403e --- /dev/null +++ b/tests/ui/linking/macos-search-path.stderr @@ -0,0 +1,11 @@ +error: ld: warning: search path '/no/such/file/or/directory' not found + + | +note: the lint level is defined here + --> $DIR/macos-search-path.rs:4:9 + | +LL | #![deny(linker_info)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/linking/windows-gnu-corrupt-drective.rs b/tests/ui/linking/windows-gnu-corrupt-drective.rs new file mode 100644 index 0000000000000..983bddd2187a8 --- /dev/null +++ b/tests/ui/linking/windows-gnu-corrupt-drective.rs @@ -0,0 +1,6 @@ +//@ only-windows-gnu +//@ build-fail +//@ compile-flags: -C linker={{src-base}}/linking/auxiliary/fake-linker.ps1 +#![deny(linker_info)] +//~? ERROR Warning: .drectve +fn main() {} diff --git a/tests/ui/linking/windows-gnu-corrupt-drective.stderr b/tests/ui/linking/windows-gnu-corrupt-drective.stderr new file mode 100644 index 0000000000000..472b31bd8f810 --- /dev/null +++ b/tests/ui/linking/windows-gnu-corrupt-drective.stderr @@ -0,0 +1,12 @@ +error: Warning: .drectve `-exclude-symbols:_ZN28windows_gnu_corrupt_drective4main17h291ed884c1aada69E ' unrecognized + Warning: corrupt .drectve at end of def file + + | +note: the lint level is defined here + --> $DIR/windows-gnu-corrupt-drective.rs:4:9 + | +LL | #![deny(linker_info)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr index ae5f6b3adece0..54994c48ea43a 100644 --- a/tests/ui/lint/linker-warning.stderr +++ b/tests/ui/lint/linker-warning.stderr @@ -20,7 +20,7 @@ warning: unused attribute LL | #![allow(linker_messages)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | - = note: the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked + = note: the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked warning: 2 warnings emitted diff --git a/tests/ui/process/nofile-limit.rs b/tests/ui/process/nofile-limit.rs index 64777b514256e..f5246856b80f2 100644 --- a/tests/ui/process/nofile-limit.rs +++ b/tests/ui/process/nofile-limit.rs @@ -11,6 +11,9 @@ #![feature(exit_status_error)] #![feature(rustc_private)] +// on aarch64, "Using 'getaddrinfo' in statically linked applications requires at runtime the shared +// libraries from the glibc version used for linking" +#![allow(linker_messages)] extern crate libc; use std::os::unix::process::CommandExt; diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index a48940460f91e..4a94b81452a90 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -8,7 +8,7 @@ macro-stats #[derive(Hash)] 2 17 8.5 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 503 503.0 macro-stats #[derive(Default)] 2 16 8.0 403 201.5 -macro-stats #[derive(Eq)] 1 11 11.0 319 319.0 +macro-stats #[derive(Eq)] 1 10 10.0 298 298.0 macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0 macro-stats #[derive(Copy)] 1 2 2.0 61 61.0