diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index fb666550e9302..3d46415507def 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -661,11 +661,11 @@ impl TokenStream { if attr_style == AttrStyle::Inner { vec![ TokenTree::token_joint(token::Pound, span), - TokenTree::token_alone(token::Not, span), + TokenTree::token_joint_hidden(token::Not, span), body, ] } else { - vec![TokenTree::token_alone(token::Pound, span), body] + vec![TokenTree::token_joint_hidden(token::Pound, span), body] } } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 545b98a9135af..f02fe4cf0a728 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -681,22 +681,40 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } + // The easiest way to implement token stream pretty printing would be to + // print each token followed by a single space. But that would produce ugly + // output, so we go to some effort to do better. + // + // First, we track whether each token that appears in source code is + // followed by a space, with `Spacing`, and reproduce that in the output. + // This works well in a lot of cases. E.g. `stringify!(x + y)` produces + // "x + y" and `stringify!(x+y)` produces "x+y". + // + // But this doesn't work for code produced by proc macros (which have no + // original source text representation) nor for code produced by decl + // macros (which are tricky because the whitespace after tokens appearing + // in macro rules isn't always what you want in the produced output). For + // these we mostly use `Spacing::Alone`, which is the conservative choice. + // + // So we have a backup mechanism for when `Spacing::Alone` occurs between a + // pair of tokens: we check if that pair of tokens can obviously go + // together without a space between them. E.g. token `x` followed by token + // `,` is better printed as `x,` than `x ,`. (Even if the original source + // code was `x ,`.) + // + // Finally, we must be careful about changing the output. Token pretty + // printing is used by `stringify!` and `impl Display for + // proc_macro::TokenStream`, and some programs rely on the output having a + // particular form, even though they shouldn't. In particular, some proc + // macros do `format!({stream})` on a token stream and then "parse" the + // output with simple string matching that can't handle whitespace changes. + // E.g. we have seen cases where a proc macro can handle `a :: b` but not + // `a::b`. See #117433 for some examples. fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { let mut iter = tts.trees().peekable(); while let Some(tt) = iter.next() { let spacing = self.print_tt(tt, convert_dollar_crate); if let Some(next) = iter.peek() { - // Should we print a space after `tt`? There are two guiding - // factors. - // - `spacing` is the more important and accurate one. Most - // tokens have good spacing information, and - // `Joint`/`JointHidden` get used a lot. - // - `space_between` is the backup. Code produced by proc - // macros has worse spacing information, with no - // `JointHidden` usage and too much `Alone` usage, which - // would result in over-spaced output such as - // `( x () , y . z )`. `space_between` avoids some of the - // excess whitespace. if spacing == Spacing::Alone && space_between(tt, next) { self.space(); } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 085ea3458bbfa..7814422611439 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -153,7 +153,7 @@ impl<'cx, 'a> Context<'cx, 'a> { fn build_panic(&self, expr_str: &str, panic_path: Path) -> P { let escaped_expr_str = escape_to_fmt(expr_str); let initial = [ - TokenTree::token_joint_hidden( + TokenTree::token_joint( token::Literal(token::Lit { kind: token::LitKind::Str, symbol: Symbol::intern(&if self.fmt_string.is_empty() { @@ -172,7 +172,7 @@ impl<'cx, 'a> Context<'cx, 'a> { ]; let captures = self.capture_decls.iter().flat_map(|cap| { [ - TokenTree::token_joint_hidden( + TokenTree::token_joint( token::Ident(cap.ident.name, IdentIsRaw::No), cap.ident.span, ), diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index bf92ddb33701c..577523a1d5a32 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::*; use crate::errors; use core::ops::ControlFlow; use rustc_ast as ast; -use rustc_ast::visit::walk_list; +use rustc_ast::visit::visit_opt; use rustc_ast::{attr, EnumDef, VariantData}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; @@ -224,7 +224,7 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' self.visit_ident(v.ident); self.visit_vis(&v.vis); self.visit_variant_data(&v.data); - walk_list!(self, visit_anon_const, &v.disr_expr); + visit_opt!(self, visit_anon_const, &v.disr_expr); for attr in &v.attrs { rustc_ast::visit::walk_attribute(self, attr); } diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index fce4690f97dc9..394c810176ab2 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -200,7 +200,7 @@ fn produce_final_output_artifacts( // to get rid of it. for output_type in crate_output.outputs.keys() { match *output_type { - OutputType::Bitcode => { + OutputType::Bitcode | OutputType::ThinLinkBitcode => { // Cranelift doesn't have bitcode // user_wants_bitcode = true; // // Copy to .bc, but always keep the .0.bc. There is a later diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 3f2fadce9e4d5..b1785e150adc5 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -335,6 +335,10 @@ impl ThinBufferMethods for ThinBuffer { fn data(&self) -> &[u8] { unimplemented!(); } + + fn thin_link_data(&self) -> &[u8] { + unimplemented!(); + } } pub struct GccContext { @@ -414,7 +418,7 @@ impl WriteBackendMethods for GccCodegenBackend { back::write::codegen(cgcx, dcx, module, config) } - fn prepare_thin(_module: ModuleCodegen) -> (String, Self::ThinBuffer) { + fn prepare_thin(_module: ModuleCodegen, _emit_summary: bool) -> (String, Self::ThinBuffer) { unimplemented!(); } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 71d4343ee07fb..db28c6857b743 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -16,6 +16,7 @@ use rustc_middle::{bug, span_bug, ty::Instance}; use rustc_span::{Pos, Span}; use rustc_target::abi::*; use rustc_target::asm::*; +use tracing::debug; use libc::{c_char, c_uint}; use smallvec::SmallVec; diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index c304c0cbd3bd5..fa7e7e5377a26 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -18,6 +18,7 @@ use rustc_codegen_ssa::back::archive::{ get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, }; +use tracing::trace; use rustc_session::cstore::DllImport; use rustc_session::Session; diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index e61af863dc079..bb7c8fe2ea7a3 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -20,6 +20,7 @@ use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; use rustc_session::config::{self, CrateType, Lto}; +use tracing::{debug, info}; use std::collections::BTreeMap; use std::ffi::{CStr, CString}; @@ -229,9 +230,12 @@ pub(crate) fn run_thin( thin_lto(cgcx, &dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold) } -pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBuffer) { +pub(crate) fn prepare_thin( + module: ModuleCodegen, + emit_summary: bool, +) -> (String, ThinBuffer) { let name = module.name; - let buffer = ThinBuffer::new(module.module_llvm.llmod(), true); + let buffer = ThinBuffer::new(module.module_llvm.llmod(), true, emit_summary); (name, buffer) } @@ -671,9 +675,9 @@ unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer { + pub fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer { unsafe { - let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin); + let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin, emit_summary); ThinBuffer(buffer) } } @@ -687,6 +691,14 @@ impl ThinBufferMethods for ThinBuffer { slice::from_raw_parts(ptr, len) } } + + fn thin_link_data(&self) -> &[u8] { + unsafe { + let ptr = llvm::LLVMRustThinLTOBufferThinLinkDataPtr(self.0) as *const _; + let len = llvm::LLVMRustThinLTOBufferThinLinkDataLen(self.0); + slice::from_raw_parts(ptr, len) + } + } } impl Drop for ThinBuffer { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 49f9d7ddab65f..02e3bb06dda3e 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -35,6 +35,7 @@ use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel}; +use tracing::debug; use crate::llvm::diagnostic::OptimizationDiagnosticKind; use libc::{c_char, c_int, c_void, size_t}; @@ -708,13 +709,15 @@ pub(crate) unsafe fn codegen( // asm from LLVM and use `gcc` to create the object file. let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + let bc_summary_out = + cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); if config.bitcode_needed() { let _timer = cgcx .prof .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name); - let thin = ThinBuffer::new(llmod, config.emit_thin_lto); + let thin = ThinBuffer::new(llmod, config.emit_thin_lto, config.emit_thin_lto_summary); let data = thin.data(); if let Some(bitcode_filename) = bc_out.file_name() { @@ -725,6 +728,25 @@ pub(crate) unsafe fn codegen( ); } + if config.emit_thin_lto_summary + && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name() + { + let summary_data = thin.thin_link_data(); + cgcx.prof.artifact_size( + "llvm_bitcode_summary", + thin_link_bitcode_filename.to_string_lossy(), + summary_data.len() as u64, + ); + + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_emit_bitcode_summary", + &*module.name, + ); + if let Err(err) = fs::write(&bc_summary_out, summary_data) { + dcx.emit_err(WriteBytecode { path: &bc_summary_out, err }); + } + } + if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx .prof diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 230c58dfcafb7..72ff9ea118e28 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -30,6 +30,7 @@ use std::borrow::Cow; use std::iter; use std::ops::Deref; use std::ptr; +use tracing::{debug, instrument}; // All Builders must have an llfn associated with them #[must_use] diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index e675362ac338c..659c6ae0d8630 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -12,6 +12,7 @@ use crate::value::Value; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; +use tracing::debug; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index ec33ce6292acc..ab8036a1410fb 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -19,6 +19,7 @@ use rustc_target::spec::Target; use libc::{c_char, c_uint}; use std::fmt::Write; +use tracing::debug; /* * A note on nomenclature of linking: "extern", "foreign", and "upcall". diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 9e85c2d88f9b4..a2314f4850c7c 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -25,6 +25,7 @@ use rustc_target::abi::{ Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange, }; use std::ops::Range; +use tracing::{debug, instrument, trace}; pub fn const_alloc_to_llvm<'ll>( cx: &CodegenCx<'ll, '_>, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index d85d9411f03b6..b969fe27a99be 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::coverage::{ }; use rustc_middle::ty::Instance; use rustc_span::Symbol; +use tracing::{debug, instrument}; /// Holds all of the coverage mapping data associated with a function instance, /// collected during traversal of `Coverage` statements in the function's MIR. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 3f3969bbca35c..d2c0f20c285b4 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -14,6 +14,7 @@ use rustc_middle::mir; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefIdSet; use rustc_span::Symbol; +use tracing::debug; /// Generates and exports the Coverage Map. /// diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 26ea95f0f0d50..7b7f8c885bbb1 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -17,6 +17,7 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Instance; use rustc_target::abi::{Align, Size}; +use tracing::{debug, instrument}; use std::cell::RefCell; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index f44738ba6421f..10d3c0d0e7443 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -41,6 +41,7 @@ use rustc_symbol_mangling::typeid_for_trait_ref; use rustc_target::abi::{Align, Size}; use rustc_target::spec::DebuginfoKind; use smallvec::smallvec; +use tracing::{debug, instrument}; use libc::{c_char, c_longlong, c_uint}; use std::borrow::Cow; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 6149c18696cf2..3486ce4becb46 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -42,6 +42,7 @@ use std::cell::OnceCell; use std::cell::RefCell; use std::iter; use std::ops::Range; +use tracing::debug; mod create_scope_map; pub mod gdb; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index c758010c58192..155e7a89fd8b9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -6,7 +6,7 @@ use super::CodegenUnitDebugContext; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::ty::{self, Ty}; -use trace; +use tracing::trace; use crate::common::CodegenCx; use crate::llvm; diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 7117c4a0ed910..bf86d0e0569b1 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_middle::ty::{Instance, Ty}; use rustc_sanitizers::{cfi, kcfi}; use smallvec::SmallVec; +use tracing::debug; /// Declare a function. /// diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 897132a8e9ccc..3d2ce550b238d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -21,6 +21,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; +use tracing::debug; use std::cmp::Ordering; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1cecf682e5db6..0029ec9d09a25 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -15,9 +15,6 @@ #![feature(let_chains)] #![feature(impl_trait_in_assoc_type)] -#[macro_use] -extern crate tracing; - use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; @@ -240,8 +237,11 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) -> Result { back::write::codegen(cgcx, dcx, module, config) } - fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { - back::lto::prepare_thin(module) + fn prepare_thin( + module: ModuleCodegen, + emit_summary: bool, + ) -> (String, Self::ThinBuffer) { + back::lto::prepare_thin(module, emit_summary) } fn serialize_module(module: ModuleCodegen) -> (String, Self::ModuleBuffer) { (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod())) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7a34e21628dc6..132e1f9e8fd93 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2350,10 +2350,16 @@ extern "C" { #[allow(improper_ctypes)] pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString); - pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferCreate( + M: &Module, + is_thin: bool, + emit_summary: bool, + ) -> &'static mut ThinLTOBuffer; pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer); pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char; pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t; + pub fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char; + pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t; pub fn LLVMRustCreateThinLTOData( Modules: *const ThinLTOModule, NumModules: c_uint, diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 29100a641712e..a7df08421a31e 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; +use tracing::debug; impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { fn predefine_static( diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 5f60fd23a5fe9..011d8ab57c75c 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_target::abi::{Abi, Align, FieldsShape}; use rustc_target::abi::{Float, Int, Pointer}; use rustc_target::abi::{Scalar, Size, Variants}; +use tracing::debug; use std::fmt::Write; diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index d159fe58d3eef..1a851ad04a1f0 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -212,6 +212,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected +codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot + codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index e441aea8400b7..6e7d736eb29d3 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -37,6 +37,7 @@ use rustc_span::{Span, Symbol}; use std::borrow::Cow; use std::fmt; use thin_vec::ThinVec; +use tracing::debug; #[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 37b8f81ad9465..bdb808b1d4fff 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -52,6 +52,7 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; +use tracing::{debug, info, warn}; pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) { if let Err(e) = fs::remove_file(path) { @@ -786,12 +787,33 @@ fn link_natively( if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) && unknown_arg_regex.is_match(&out) && out.contains("-no-pie") - && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") + && cmd.get_args().iter().any(|e| e == "-no-pie") { info!("linker output: {:?}", out); warn!("Linker does not support -no-pie command line option. Retrying without."); for arg in cmd.take_args() { - if arg.to_string_lossy() != "-no-pie" { + if arg != "-no-pie" { + cmd.arg(arg); + } + } + info!("{:?}", &cmd); + continue; + } + + // Check if linking failed with an error message that indicates the driver didn't recognize + // the `-fuse-ld=lld` option. If so, re-perform the link step without it. This avoids having + // to spawn multiple instances on the happy path to do version checking, and ensures things + // keep working on the tier 1 baseline of GLIBC 2.17+. That is generally understood as GCCs + // circa RHEL/CentOS 7, 4.5 or so, whereas lld support was added in GCC 9. + if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, Lld::Yes)) + && unknown_arg_regex.is_match(&out) + && out.contains("-fuse-ld=lld") + && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-fuse-ld=lld") + { + info!("linker output: {:?}", out); + warn!("The linker driver does not support `-fuse-ld=lld`. Retrying without it."); + for arg in cmd.take_args() { + if arg.to_string_lossy() != "-fuse-ld=lld" { cmd.arg(arg); } } @@ -804,7 +826,7 @@ fn link_natively( if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) && unknown_arg_regex.is_match(&out) && (out.contains("-static-pie") || out.contains("--no-dynamic-linker")) - && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie") + && cmd.get_args().iter().any(|e| e == "-static-pie") { info!("linker output: {:?}", out); warn!( @@ -843,7 +865,7 @@ fn link_natively( assert!(pre_objects_static.is_empty() || !pre_objects_static_pie.is_empty()); assert!(post_objects_static.is_empty() || !post_objects_static_pie.is_empty()); for arg in cmd.take_args() { - if arg.to_string_lossy() == "-static-pie" { + if arg == "-static-pie" { // Replace the output kind. cmd.arg("-static"); } else if pre_objects_static_pie.contains(&arg) { @@ -3119,13 +3141,21 @@ fn add_lld_args( let self_contained_linker = self_contained_cli || self_contained_target; if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() { + let mut linker_path_exists = false; for path in sess.get_tools_search_paths(false) { + let linker_path = path.join("gcc-ld"); + linker_path_exists |= linker_path.exists(); cmd.arg({ let mut arg = OsString::from("-B"); - arg.push(path.join("gcc-ld")); + arg.push(linker_path); arg }); } + if !linker_path_exists { + // As a sanity check, we emit an error if none of these paths exist: we want + // self-contained linking and have no linker. + sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing); + } } // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index f85056f8ad410..a82478900b17f 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -22,6 +22,7 @@ use rustc_session::Session; use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld}; use cc::windows_registry; +use tracing::{debug, warn}; /// Disables non-English messages from localized linkers. /// Such messages may cause issues with text encoding on Windows (#35785) diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index ebbf49af18487..3114f1c38ae71 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_fs_util::try_canonicalize; use std::ffi::OsString; use std::path::{Path, PathBuf}; +use tracing::debug; pub struct RPathConfig<'a> { pub libs: &'a [&'a Path], diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 0e335bf00cf05..79d6641a0da1a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; use rustc_target::spec::{SanitizerSet, TlsModel}; +use tracing::debug; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(tcx.crate_types()) @@ -399,7 +400,7 @@ fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), ) -> DefIdMap, CrateNum>> { - let cnums = tcx.crates(()); + let cnums = tcx.used_crates(()); let mut instances: DefIdMap> = Default::default(); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 53ba0da7d0490..d57f4ddf8aaec 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -49,6 +49,7 @@ use std::str; use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::Arc; use std::thread; +use tracing::debug; const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; @@ -107,6 +108,7 @@ pub struct ModuleConfig { pub emit_asm: bool, pub emit_obj: EmitObj, pub emit_thin_lto: bool, + pub emit_thin_lto_summary: bool, pub bc_cmdline: String, // Miscellaneous flags. These are mostly copied from command-line @@ -231,6 +233,10 @@ impl ModuleConfig { ), emit_obj, emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto, + emit_thin_lto_summary: if_regular!( + sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode), + false + ), bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(), verify_llvm_ir: sess.verify_llvm_ir(), @@ -282,6 +288,7 @@ impl ModuleConfig { pub fn bitcode_needed(&self) -> bool { self.emit_bc + || self.emit_thin_lto_summary || self.emit_obj == EmitObj::Bitcode || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) } @@ -629,6 +636,9 @@ fn produce_final_output_artifacts( // them for making an rlib. copy_if_one_unit(OutputType::Bitcode, true); } + OutputType::ThinLinkBitcode => { + copy_if_one_unit(OutputType::ThinLinkBitcode, false); + } OutputType::LlvmAssembly => { copy_if_one_unit(OutputType::LlvmAssembly, false); } @@ -882,7 +892,7 @@ fn execute_optimize_work_item( match lto_type { ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config), ComputedLtoType::Thin => { - let (name, thin_buffer) = B::prepare_thin(module); + let (name, thin_buffer) = B::prepare_thin(module, false); if let Some(path) = bitcode { fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| { panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 66bc5b6606ded..b4556f8fcb8fc 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -45,6 +45,7 @@ use std::collections::BTreeSet; use std::time::{Duration, Instant}; use itertools::Itertools; +use tracing::{debug, info}; pub fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { match op { @@ -539,7 +540,7 @@ pub fn collect_debugger_visualizers_transitive( tcx.debugger_visualizers(LOCAL_CRATE) .iter() .chain( - tcx.crates(()) + tcx.used_crates(()) .iter() .filter(|&cnum| { let used_crate_source = tcx.used_crate_source(*cnum); @@ -849,7 +850,7 @@ impl CrateInfo { // `compiler_builtins` are always placed last to ensure that they're linked correctly. used_crates.extend(compiler_builtins); - let crates = tcx.crates(()); + let crates = tcx.used_crates(()); let n_crates = crates.len(); let mut info = CrateInfo { target_cpu, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ed6a0c2441061..3641e7842cfbb 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -413,6 +413,10 @@ pub struct UnableToExeLinker { #[diag(codegen_ssa_msvc_missing_linker)] pub struct MsvcMissingLinker; +#[derive(Diagnostic)] +#[diag(codegen_ssa_self_contained_linker_missing)] +pub struct SelfContainedLinkerMissing; + #[derive(Diagnostic)] #[diag(codegen_ssa_check_installed_visual_studio)] pub struct CheckInstalledVisualStudio; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 66a7a2e090ae6..1668104d7e22f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -15,9 +15,6 @@ //! The backend-agnostic functions of this crate use functions defined in various traits that //! have to be implemented by each backend. -#[macro_use] -extern crate tracing; - use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexMap; diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 23036e9bea022..d6fc8e536b444 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -5,6 +5,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::config::Lto; use rustc_symbol_mangling::typeid_for_trait_ref; use rustc_target::abi::call::FnAbi; +use tracing::{debug, instrument}; #[derive(Copy, Clone, Debug)] pub struct VirtualIndex(u64); diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 09ae7cf64109b..0577ba32ffdcc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -11,6 +11,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::{bug, span_bug}; +use tracing::debug; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ba6aad51316cb..1cb1ba99a5ab2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -24,6 +24,7 @@ use rustc_span::{source_map::Spanned, sym, Span}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; +use tracing::{debug, info}; use std::cmp; diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs index 7db260c9f5bd8..c7f63eab8298d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/locals.rs +++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs @@ -7,6 +7,8 @@ use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::print::with_no_trimmed_paths; use std::ops::{Index, IndexMut}; +use tracing::{debug, warn}; + pub(super) struct Locals<'tcx, V> { values: IndexVec>, } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index cf6e2e8d14c6c..e8da98428829e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_target::abi::call::{FnAbi, PassMode}; +use tracing::{debug, instrument}; use std::iter; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 32fd9b657f99c..5b2f9a3be2792 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -16,6 +16,7 @@ use std::fmt; use arrayvec::ArrayVec; use either::Either; +use tracing::debug; /// The representation of a Rust value. The enum variant is in fact /// uniquely determined by the value's type, but is kept as a diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 971ac2defdc0d..7c3569a9dd2e2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -12,6 +12,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{Align, FieldsShape, Int, Pointer, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; +use tracing::{debug, instrument}; /// The location and extra runtime properties of the place. /// @@ -159,9 +160,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx.inbounds_ptradd(self.val.llval, bx.const_usize(offset.bytes())) }; let val = PlaceValue { - llval, + llval, llextra: if bx.cx().type_has_metadata(field.ty) { self.val.llextra } else { None }, - align: effective_field_align, + align: effective_field_align, }; val.with_type(field) }; @@ -408,9 +409,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { }; let llval = bx.inbounds_gep( - bx.cx().backend_type(self.layout), - self.val.llval, - &[bx.cx().const_usize(0), llindex], + bx.cx().backend_type(self.layout), + self.val.llval, + &[bx.cx().const_usize(0), llindex], ); let align = self.val.align.restrict_for_offset(offset); PlaceValue::new_sized(llval, align).with_type(layout) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f9085f502d422..4dd80d34ea703 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -17,6 +17,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT}; use arrayvec::ArrayVec; +use tracing::{debug, instrument}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { #[instrument(level = "trace", skip(self, bx))] diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index a0429022587ce..27494f48b099b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,6 +1,7 @@ use rustc_middle::mir::{self, NonDivergingIntrinsic}; use rustc_middle::span_bug; use rustc_session::config::OptLevel; +use tracing::instrument; use super::FunctionCx; use super::LocalRef; diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 40921c2932fa9..0fbcb938d1a74 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -9,6 +9,7 @@ use rustc_middle::span_bug; use rustc_middle::ty; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Instance; +use tracing::debug; pub trait MonoItemExt<'a, 'tcx> { fn define>(&self, cx: &'a Bx::CodegenCx); diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 032699f1fa15a..130fe2eaf2feb 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -9,6 +9,7 @@ use rustc_middle::bug; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::WrappingRange; +use tracing::{debug, trace}; pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index 048540894ac9b..f83e34ab01bc2 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -56,12 +56,16 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { module: ModuleCodegen, config: &ModuleConfig, ) -> Result; - fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer); + fn prepare_thin( + module: ModuleCodegen, + want_summary: bool, + ) -> (String, Self::ThinBuffer); fn serialize_module(module: ModuleCodegen) -> (String, Self::ModuleBuffer); } pub trait ThinBufferMethods: Send + Sync { fn data(&self) -> &[u8]; + fn thin_link_data(&self) -> &[u8]; } pub trait ModuleBufferMethods: Send + Sync { diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 20f0f27517ffe..2dbeb7d5e0ca4 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -246,11 +246,10 @@ const_eval_offset_from_unsigned_overflow = const_eval_operator_non_const = cannot call non-const operator in {const_eval_const_context}s -const_eval_overflow = - overflow executing `{$name}` - +const_eval_overflow_arith = + arithmetic overflow in `{$intrinsic}` const_eval_overflow_shift = - overflowing shift by {$val} in `{$name}` + overflowing shift by {$shift_amount} in `{$intrinsic}` const_eval_panic = the evaluated program panicked at '{$msg}', {$file}:{$line}:{$col} diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 94c9f056b302e..530a05a1ed88c 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -125,7 +125,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine { bin_op: BinOp, left: &interpret::ImmTy<'tcx, Self::Provenance>, right: &interpret::ImmTy<'tcx, Self::Provenance>, - ) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> { + ) -> interpret::InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> { use rustc_middle::mir::BinOp::*; Ok(match bin_op { Eq | Ne | Lt | Le | Gt | Ge => { @@ -154,7 +154,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine { Ge => left >= right, _ => bug!(), }; - (ImmTy::from_bool(res, *ecx.tcx), false) + ImmTy::from_bool(res, *ecx.tcx) } // Some more operations are possible with atomics. diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 08c9609eacfa4..7a1c2a7b6fa51 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -2,7 +2,7 @@ use std::mem; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg}; use rustc_hir::CRATE_HIR_ID; -use rustc_middle::mir::interpret::Provenance; +use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo}; use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::TyCtxt; @@ -139,9 +139,10 @@ where ErrorHandled::TooGeneric(span) } err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span), - err_inval!(Layout(LayoutError::ReferencesError(guar))) => { - ErrorHandled::Reported(guar.into(), span) - } + err_inval!(Layout(LayoutError::ReferencesError(guar))) => ErrorHandled::Reported( + ReportedErrorInfo::tainted_by_errors(guar), + span, + ), // Report remaining errors. _ => { let (our_span, frames) = get_span_and_frames(); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6a9a21bbd8e06..966951e7d9a45 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,6 +1,7 @@ use std::sync::atomic::Ordering::Relaxed; use either::{Left, Right}; +use tracing::{debug, instrument, trace}; use rustc_hir::def::DefKind; use rustc_middle::bug; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 310fd462d5f8c..b8b4426c2ec6a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi as CallAbi; +use tracing::debug; use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; @@ -589,7 +590,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _bin_op: mir::BinOp, _left: &ImmTy<'tcx>, _right: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, (ImmTy<'tcx>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx>> { throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time"); } diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index a5c8c0bb82ad7..4ae4816e33ab9 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::InterpErrorInfo; use rustc_middle::query::{Key, TyCtxtAt}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; +use tracing::instrument; use crate::interpret::{format_interp_error, InterpCx}; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index fbf2ca5ab0a62..b906bfa775f88 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_target::abi::{Abi, VariantIdx}; +use tracing::{debug, instrument, trace}; use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const}; use super::machine::CompileTimeEvalContext; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 90d4f1168e4fd..e5ea4c3442eac 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; +use either::Either; use rustc_errors::{ codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, Diagnostic, EmissionGuarantee, Level, }; @@ -481,6 +482,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { DivisionOverflow => const_eval_division_overflow, RemainderOverflow => const_eval_remainder_overflow, PointerArithOverflow => const_eval_pointer_arithmetic_overflow, + ArithOverflow { .. } => const_eval_overflow_arith, + ShiftOverflow { .. } => const_eval_overflow_shift, InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, UnterminatedCString(_) => const_eval_unterminated_c_string, @@ -539,6 +542,19 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | UninhabitedEnumVariantWritten(_) | UninhabitedEnumVariantRead(_) => {} + ArithOverflow { intrinsic } => { + diag.arg("intrinsic", intrinsic); + } + ShiftOverflow { intrinsic, shift_amount } => { + diag.arg("intrinsic", intrinsic); + diag.arg( + "shift_amount", + match shift_amount { + Either::Left(v) => v.to_string(), + Either::Right(v) => v.to_string(), + }, + ); + } BoundsCheckFailed { len, index } => { diag.arg("len", len); diag.arg("index", index); diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 799e12f9ac97b..ecfb25e32cda7 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_middle::{bug, span_bug}; use rustc_target::abi::Integer; use rustc_type_ir::TyKind::*; +use tracing::trace; use super::{ err_inval, throw_ub, throw_ub_custom, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 8ddc741de239a..0790f06e6e1d8 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; use rustc_middle::ty::{self, ScalarInt, Ty}; use rustc_target::abi::{self, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; +use tracing::{instrument, trace}; use super::{ err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable, @@ -172,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let tag_val = ImmTy::from_uint(tag_bits, tag_layout); let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = - self.wrapping_binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; + self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; let variant_index_relative = variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size); // Check if this is in the range that indicates an actual discriminant. @@ -292,11 +293,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let variant_index_relative_val = ImmTy::from_uint(variant_index_relative, tag_layout); let tag = self - .wrapping_binary_op( - mir::BinOp::Add, - &variant_index_relative_val, - &niche_start_val, - )? + .binary_op(mir::BinOp::Add, &variant_index_relative_val, &niche_start_val)? .to_scalar() .assert_int(); Ok(Some((tag, tag_field))) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 344bb7cd98be9..d82623fa0094f 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -2,6 +2,7 @@ use std::cell::Cell; use std::{fmt, mem}; use either::{Either, Left, Right}; +use tracing::{debug, info, info_span, instrument, trace}; use hir::CRATE_HIR_ID; use rustc_errors::DiagCtxt; @@ -1181,9 +1182,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| { - if M::ALL_CONSTS_ARE_PRECHECKED && !matches!(err, ErrorHandled::TooGeneric(..)) { - // Looks like the const is not captued by `required_consts`, that's bad. - bug!("interpret const eval failure of {val:?} which is not in required_consts"); + if M::ALL_CONSTS_ARE_PRECHECKED { + match err { + ErrorHandled::TooGeneric(..) => {}, + ErrorHandled::Reported(reported, span) => { + if reported.is_tainted_by_errors() { + // const-eval will return "tainted" errors if e.g. the layout cannot + // be computed as the type references non-existing names. + // See . + } else { + // Looks like the const is not captued by `required_consts`, that's bad. + span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts"); + } + } + } } err.emit_note(*ecx.tcx); err diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 3565b4fb51657..c34b658fb3738 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -23,6 +23,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::def_id::LocalDefId; use rustc_span::sym; +use tracing::{instrument, trace}; use super::{err_ub, AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 72dad562695e2..3a8f8dc4cb9dd 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -14,6 +14,7 @@ use rustc_middle::{ }; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::Size; +use tracing::trace; use super::{ err_inval, err_ub_custom, err_unsup_format, memory::MemoryKind, throw_inval, throw_ub_custom, @@ -286,9 +287,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (val, overflowed) = { let a_offset = ImmTy::from_uint(a_offset, usize_layout); let b_offset = ImmTy::from_uint(b_offset, usize_layout); - self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)? + self.binary_op(BinOp::SubWithOverflow, &a_offset, &b_offset)? + .to_scalar_pair() }; - if overflowed { + if overflowed.to_bool()? { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( @@ -300,7 +302,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The signed form of the intrinsic allows this. If we interpret the // difference as isize, we'll get the proper signed difference. If that // seems *positive*, they were more than isize::MAX apart. - let dist = val.to_scalar().to_target_isize(self)?; + let dist = val.to_target_isize(self)?; if dist >= 0 { throw_ub_custom!( fluent::const_eval_offset_from_underflow, @@ -310,7 +312,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dist } else { // b >= a - let dist = val.to_scalar().to_target_isize(self)?; + let dist = val.to_target_isize(self)?; // If converting to isize produced a *negative* result, we had an overflow // because they were more than isize::MAX apart. if dist < 0 { @@ -516,9 +518,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. // First, check x % y != 0 (or if that computation overflows). - let (res, overflow) = self.overflowing_binary_op(BinOp::Rem, a, b)?; - assert!(!overflow); // All overflow is UB, so this should never return on overflow. - if res.to_scalar().assert_bits(a.layout.size) != 0 { + let rem = self.binary_op(BinOp::Rem, a, b)?; + if rem.to_scalar().assert_bits(a.layout.size) != 0 { throw_ub_custom!( fluent::const_eval_exact_div_has_remainder, a = format!("{a}"), @@ -526,7 +527,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } // `Rem` says this is all right, so we can let `Div` do its job. - self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into()) + let res = self.binary_op(BinOp::Div, a, b)?; + self.write_immediate(*res, dest) } pub fn saturating_arith( @@ -539,8 +541,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); assert!(matches!(mir_op, BinOp::Add | BinOp::Sub)); - let (val, overflowed) = self.overflowing_binary_op(mir_op, l, r)?; - Ok(if overflowed { + let (val, overflowed) = + self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair(); + Ok(if overflowed.to_bool()? { let size = l.layout.size; let num_bits = size.bits(); if l.layout.abi.is_signed() { @@ -571,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } else { - val.to_scalar() + val }) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 2eaebc1924bc6..72a16dbe4d6a0 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -252,7 +252,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { bin_op: mir::BinOp, left: &ImmTy<'tcx, Self::Provenance>, right: &ImmTy<'tcx, Self::Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)>; + ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>>; /// Generate the NaN returned by a float operation, given the list of inputs. /// (This is all inputs, not just NaN inputs!) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 737f2fd8bb983..23273e6944416 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -21,6 +21,8 @@ use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; +use tracing::{debug, instrument, trace}; + use crate::fluent_generated as fluent; use super::{ diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index bad9732f48310..8f01b8720104e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,10 +4,11 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; +use tracing::trace; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -249,6 +250,15 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { Self::from_scalar(Scalar::from_i8(c as i8), layout) } + pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self { + let layout = tcx + .layout_of( + ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), + ) + .unwrap(); + Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout) + } + /// Return the immediate as a `ScalarInt`. Ensures that it has the size that the layout of the /// immediate indicates. #[inline] @@ -270,6 +280,17 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral()) } + #[inline] + #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) + pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) { + let layout = self.layout; + let (val0, val1) = self.to_scalar_pair(); + ( + ImmTy::from_scalar(val0, layout.field(cx, 0)), + ImmTy::from_scalar(val1, layout.field(cx, 1)), + ) + } + /// Compute the "sub-immediate" that is located within the `base` at the given offset with the /// given layout. // Not called `offset` to avoid confusion with the trait method. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 5f59e3d887e46..62641b868e623 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,78 +1,23 @@ +use either::Either; + use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; +use rustc_middle::ty::{self, FloatTy, ScalarInt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; -use rustc_target::abi::Abi; - -use super::{err_ub, throw_ub, throw_ub_custom, ImmTy, Immediate, InterpCx, Machine, PlaceTy}; +use tracing::trace; -use crate::fluent_generated as fluent; - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// Applies the binary operation `op` to the two operands and writes a tuple of the result - /// and a boolean signifying the potential overflow to the destination. - pub fn binop_with_overflow( - &mut self, - op: mir::BinOp, - left: &ImmTy<'tcx, M::Provenance>, - right: &ImmTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx> { - let (val, overflowed) = self.overflowing_binary_op(op, left, right)?; - debug_assert_eq!( - Ty::new_tup(self.tcx.tcx, &[val.layout.ty, self.tcx.types.bool]), - dest.layout.ty, - "type mismatch for result of {op:?}", - ); - // Write the result to `dest`. - if let Abi::ScalarPair(..) = dest.layout.abi { - // We can use the optimized path and avoid `place_field` (which might do - // `force_allocation`). - let pair = Immediate::ScalarPair(val.to_scalar(), Scalar::from_bool(overflowed)); - self.write_immediate(pair, dest)?; - } else { - assert!(self.tcx.sess.opts.unstable_opts.randomize_layout); - // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to - // do a component-wise write here. This code path is slower than the above because - // `place_field` will have to `force_allocate` locals here. - let val_field = self.project_field(dest, 0)?; - self.write_scalar(val.to_scalar(), &val_field)?; - let overflowed_field = self.project_field(dest, 1)?; - self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?; - } - Ok(()) - } - - /// Applies the binary operation `op` to the arguments and writes the result to the - /// destination. - pub fn binop_ignore_overflow( - &mut self, - op: mir::BinOp, - left: &ImmTy<'tcx, M::Provenance>, - right: &ImmTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx> { - let val = self.wrapping_binary_op(op, left, right)?; - assert_eq!(val.layout.ty, dest.layout.ty, "type mismatch for result of {op:?}"); - self.write_immediate(*val, dest) - } -} +use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine}; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - fn three_way_compare(&self, lhs: T, rhs: T) -> (ImmTy<'tcx, M::Provenance>, bool) { + fn three_way_compare(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> { let res = Ord::cmp(&lhs, &rhs); - return (ImmTy::from_ordering(res, *self.tcx), false); + return ImmTy::from_ordering(res, *self.tcx); } - fn binary_char_op( - &self, - bin_op: mir::BinOp, - l: char, - r: char, - ) -> (ImmTy<'tcx, M::Provenance>, bool) { + fn binary_char_op(&self, bin_op: mir::BinOp, l: char, r: char) -> ImmTy<'tcx, M::Provenance> { use rustc_middle::mir::BinOp::*; if bin_op == Cmp { @@ -88,15 +33,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ge => l >= r, _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op), }; - (ImmTy::from_bool(res, *self.tcx), false) + ImmTy::from_bool(res, *self.tcx) } - fn binary_bool_op( - &self, - bin_op: mir::BinOp, - l: bool, - r: bool, - ) -> (ImmTy<'tcx, M::Provenance>, bool) { + fn binary_bool_op(&self, bin_op: mir::BinOp, l: bool, r: bool) -> ImmTy<'tcx, M::Provenance> { use rustc_middle::mir::BinOp::*; let res = match bin_op { @@ -111,7 +51,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => l ^ r, _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op), }; - (ImmTy::from_bool(res, *self.tcx), false) + ImmTy::from_bool(res, *self.tcx) } fn binary_float_op + Into>>( @@ -120,14 +60,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { layout: TyAndLayout<'tcx>, l: F, r: F, - ) -> (ImmTy<'tcx, M::Provenance>, bool) { + ) -> ImmTy<'tcx, M::Provenance> { use rustc_middle::mir::BinOp::*; // Performs appropriate non-deterministic adjustments of NaN results. let adjust_nan = |f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } }; - let val = match bin_op { + match bin_op { Eq => ImmTy::from_bool(l == r, *self.tcx), Ne => ImmTy::from_bool(l != r, *self.tcx), Lt => ImmTy::from_bool(l < r, *self.tcx), @@ -140,8 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Div => ImmTy::from_scalar(adjust_nan((l / r).value).into(), layout), Rem => ImmTy::from_scalar(adjust_nan((l % r).value).into(), layout), _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op), - }; - (val, false) + } } fn binary_int_op( @@ -149,7 +88,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_middle::mir::BinOp::*; // This checks the size, so that we can just assert it below. @@ -169,25 +108,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ShrUnchecked => Some(sym::unchecked_shr), _ => None, }; + let with_overflow = bin_op.is_overflowing(); // Shift ops can have an RHS with a different numeric type. if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) { let size = left.layout.size.bits(); - // The shift offset is implicitly masked to the type size. (This is the one MIR operator - // that does *not* directly map to a single LLVM operation.) Compute how much we - // actually shift and whether there was an overflow due to shifting too much. + // Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is + // the one MIR operator that does *not* directly map to a single LLVM operation.) let (shift_amount, overflow) = if right.layout.abi.is_signed() { let shift_amount = r_signed(); let overflow = shift_amount < 0 || shift_amount >= i128::from(size); // Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result // of the `as` will be equal modulo `size` (since it is a power of two). let masked_amount = (shift_amount as u128) % u128::from(size); - assert_eq!(overflow, shift_amount != (masked_amount as i128)); + assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap()); (masked_amount, overflow) } else { let shift_amount = r_unsigned(); + let overflow = shift_amount >= u128::from(size); let masked_amount = shift_amount % u128::from(size); - (masked_amount, shift_amount != masked_amount) + assert_eq!(overflow, shift_amount != masked_amount); + (masked_amount, overflow) }; let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit // Compute the shifted result. @@ -209,19 +150,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ScalarInt::truncate_from_uint(result, left.layout.size).0 }; - if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { - throw_ub_custom!( - fluent::const_eval_overflow_shift, - val = if right.layout.abi.is_signed() { - r_signed().to_string() + if overflow && let Some(intrinsic) = throw_ub_on_overflow { + throw_ub!(ShiftOverflow { + intrinsic, + shift_amount: if right.layout.abi.is_signed() { + Either::Right(r_signed()) } else { - r_unsigned().to_string() - }, - name = intrinsic_name - ); + Either::Left(r_unsigned()) + } + }); } - return Ok((ImmTy::from_scalar_int(result, left.layout), overflow)); + return Ok(ImmTy::from_scalar_int(result, left.layout)); } // For the remaining ops, the types must be the same on both sides @@ -246,7 +186,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => None, }; if let Some(op) = op { - return Ok((ImmTy::from_bool(op(&l_signed(), &r_signed()), *self.tcx), false)); + return Ok(ImmTy::from_bool(op(&l_signed(), &r_signed()), *self.tcx)); } if bin_op == Cmp { return Ok(self.three_way_compare(l_signed(), r_signed())); @@ -256,9 +196,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Rem if r.is_null() => throw_ub!(RemainderByZero), Div => Some(i128::overflowing_div), Rem => Some(i128::overflowing_rem), - Add | AddUnchecked => Some(i128::overflowing_add), - Sub | SubUnchecked => Some(i128::overflowing_sub), - Mul | MulUnchecked => Some(i128::overflowing_mul), + Add | AddUnchecked | AddWithOverflow => Some(i128::overflowing_add), + Sub | SubUnchecked | SubWithOverflow => Some(i128::overflowing_sub), + Mul | MulUnchecked | MulWithOverflow => Some(i128::overflowing_mul), _ => None, }; if let Some(op) = op { @@ -282,10 +222,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // If that truncation loses any information, we have an overflow. let (result, lossy) = ScalarInt::truncate_from_int(result, left.layout.size); let overflow = oflo || lossy; - if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { - throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name); + if overflow && let Some(intrinsic) = throw_ub_on_overflow { + throw_ub!(ArithOverflow { intrinsic }); } - return Ok((ImmTy::from_scalar_int(result, left.layout), overflow)); + let res = ImmTy::from_scalar_int(result, left.layout); + return Ok(if with_overflow { + let overflow = ImmTy::from_bool(overflow, *self.tcx); + ImmTy::from_pair(res, overflow, *self.tcx) + } else { + res + }); } } // From here on it's okay to treat everything as unsigned. @@ -296,7 +242,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(self.three_way_compare(l, r)); } - let val = match bin_op { + Ok(match bin_op { Eq => ImmTy::from_bool(l == r, *self.tcx), Ne => ImmTy::from_bool(l != r, *self.tcx), @@ -309,40 +255,42 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitAnd => ImmTy::from_uint(l & r, left.layout), BitXor => ImmTy::from_uint(l ^ r, left.layout), - Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => { + _ => { assert!(!left.layout.abi.is_signed()); let op: fn(u128, u128) -> (u128, bool) = match bin_op { - Add | AddUnchecked => u128::overflowing_add, - Sub | SubUnchecked => u128::overflowing_sub, - Mul | MulUnchecked => u128::overflowing_mul, + Add | AddUnchecked | AddWithOverflow => u128::overflowing_add, + Sub | SubUnchecked | SubWithOverflow => u128::overflowing_sub, + Mul | MulUnchecked | MulWithOverflow => u128::overflowing_mul, Div if r == 0 => throw_ub!(DivisionByZero), Rem if r == 0 => throw_ub!(RemainderByZero), Div => u128::overflowing_div, Rem => u128::overflowing_rem, - _ => bug!(), + _ => span_bug!( + self.cur_span(), + "invalid binary op {:?}: {:?}, {:?} (both {})", + bin_op, + left, + right, + right.layout.ty, + ), }; let (result, oflo) = op(l, r); // Truncate to target type. // If that truncation loses any information, we have an overflow. let (result, lossy) = ScalarInt::truncate_from_uint(result, left.layout.size); let overflow = oflo || lossy; - if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { - throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name); + if overflow && let Some(intrinsic) = throw_ub_on_overflow { + throw_ub!(ArithOverflow { intrinsic }); + } + let res = ImmTy::from_scalar_int(result, left.layout); + if with_overflow { + let overflow = ImmTy::from_bool(overflow, *self.tcx); + ImmTy::from_pair(res, overflow, *self.tcx) + } else { + res } - return Ok((ImmTy::from_scalar_int(result, left.layout), overflow)); } - - _ => span_bug!( - self.cur_span(), - "invalid binary op {:?}: {:?}, {:?} (both {})", - bin_op, - left, - right, - right.layout.ty, - ), - }; - - Ok((val, false)) + }) } fn binary_ptr_op( @@ -350,7 +298,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_middle::mir::BinOp::*; match bin_op { @@ -369,10 +317,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?; let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?; - Ok(( - ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout), - false, - )) + Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout)) } // Fall back to machine hook so Miri can support more pointer ops. @@ -380,13 +325,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - /// Returns the result of the specified operation, and whether it overflowed. - pub fn overflowing_binary_op( + /// Returns the result of the specified operation. + /// + /// Whether this produces a scalar or a pair depends on the specific `bin_op`. + pub fn binary_op( &self, bin_op: mir::BinOp, left: &ImmTy<'tcx, M::Provenance>, right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { trace!( "Running binary op {:?}: {:?} ({}), {:?} ({})", bin_op, @@ -458,24 +405,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - #[inline] - pub fn wrapping_binary_op( - &self, - bin_op: mir::BinOp, - left: &ImmTy<'tcx, M::Provenance>, - right: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - let (val, _overflow) = self.overflowing_binary_op(bin_op, left, right)?; - Ok(val) - } - /// Returns the result of the specified operation, whether it overflowed, and /// the result type. - pub fn overflowing_unary_op( + pub fn unary_op( &self, un_op: mir::UnOp, val: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { use rustc_middle::mir::UnOp::*; let layout = val.layout; @@ -489,7 +425,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Not => !val, _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op), }; - Ok((ImmTy::from_bool(res, *self.tcx), false)) + Ok(ImmTy::from_bool(res, *self.tcx)) } ty::Float(fty) => { // No NaN adjustment here, `-` is a bitwise operation! @@ -498,37 +434,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op), }; - Ok((ImmTy::from_scalar(res, layout), false)) + Ok(ImmTy::from_scalar(res, layout)) } _ => { assert!(layout.ty.is_integral()); let val = val.to_bits(layout.size)?; - let (res, overflow) = match un_op { - Not => (self.truncate(!val, layout), false), // bitwise negation, then truncate + let res = match un_op { + Not => self.truncate(!val, layout), // bitwise negation, then truncate Neg => { // arithmetic negation assert!(layout.abi.is_signed()); let val = self.sign_extend(val, layout) as i128; - let (res, overflow) = val.overflowing_neg(); + let res = val.wrapping_neg(); let res = res as u128; // Truncate to target type. - // If that truncation loses any information, we have an overflow. - let truncated = self.truncate(res, layout); - (truncated, overflow || self.sign_extend(truncated, layout) != res) + self.truncate(res, layout) } }; - Ok((ImmTy::from_uint(res, layout), overflow)) + Ok(ImmTy::from_uint(res, layout)) } } } - - #[inline] - pub fn wrapping_unary_op( - &self, - un_op: mir::UnOp, - val: &ImmTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - let (val, _overflow) = self.overflowing_unary_op(un_op, val)?; - Ok(val) - } } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 9ced825853bd2..588db0f547f8c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -5,6 +5,7 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; +use tracing::{instrument, trace}; use rustc_ast::Mutability; use rustc_middle::mir; diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 0a2fedb48401c..cfc4d701aa7b1 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -18,6 +18,8 @@ use rustc_middle::{bug, span_bug}; use rustc_target::abi::Size; use rustc_target::abi::{self, VariantIdx}; +use tracing::{debug, instrument}; + use super::{ throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Provenance, Scalar, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index cb72d55a9ba18..58210fe39713c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -3,6 +3,7 @@ //! The main entry point is the `step` method. use either::Either; +use tracing::{info, instrument, trace}; use rustc_index::IndexSlice; use rustc_middle::mir; @@ -167,19 +168,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let left = self.read_immediate(&self.eval_operand(left, layout)?)?; let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout); let right = self.read_immediate(&self.eval_operand(right, layout)?)?; - if let Some(bin_op) = bin_op.overflowing_to_wrapping() { - self.binop_with_overflow(bin_op, &left, &right, &dest)?; - } else { - self.binop_ignore_overflow(bin_op, &left, &right, &dest)?; - } + let result = self.binary_op(bin_op, &left, &right)?; + assert_eq!(result.layout, dest.layout, "layout mismatch for result of {bin_op:?}"); + self.write_immediate(*result, &dest)?; } UnaryOp(un_op, ref operand) => { // The operand always has the same type as the result. let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?; - let val = self.wrapping_unary_op(un_op, &val)?; - assert_eq!(val.layout, dest.layout, "layout mismatch for result of {un_op:?}"); - self.write_immediate(*val, &dest)?; + let result = self.unary_op(un_op, &val)?; + assert_eq!(result.layout, dest.layout, "layout mismatch for result of {un_op:?}"); + self.write_immediate(*result, &dest)?; } Aggregate(box ref kind, ref operands) => { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b82c18578588b..360cefb5a1fed 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use either::Either; +use tracing::trace; use rustc_middle::span_bug; use rustc_middle::{ @@ -97,7 +98,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (const_int, target) in targets.iter() { // Compare using MIR BinOp::Eq, to also support pointer values. // (Avoiding `self.binary_op` as that does some redundant layout computation.) - let res = self.wrapping_binary_op( + let res = self.binary_op( mir::BinOp::Eq, &discr, &ImmTy::from_uint(const_int, discr.layout), diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index b603ef0d27a47..8b59045940519 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::interpret::{InterpResult, Pointer}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::{Align, Size}; +use tracing::trace; use super::util::ensure_monomorphic_enough; use super::{InterpCx, Machine}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index e304d1e1cc5e4..f0f9df73d9471 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use std::ops::ControlFlow; +use tracing::debug; use super::{throw_inval, InterpCx, MPlaceTy, MemPlaceMeta, MemoryKind}; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index e36d30184c858..cf6027a312fa2 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -8,6 +8,7 @@ use std::fmt::Write; use std::num::NonZero; use either::{Left, Right}; +use tracing::trace; use hir::def::DefKind; use rustc_ast::Mutability; diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 59bcc5174cb2b..692eb6c17e6ce 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::FieldIdx; use rustc_target::abi::{FieldsShape, VariantIdx, Variants}; +use tracing::trace; use std::num::NonZero; diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 7b293e2b5337a..b14780c0d98c2 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -14,9 +14,6 @@ #![feature(yeet_expr)] #![feature(if_let_guard)] -#[macro_use] -extern crate tracing; - pub mod const_eval; mod errors; pub mod interpret; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index c8c54143f6185..5fbf5b41109f1 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -20,6 +20,8 @@ use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; use std::ops::Deref; +use tracing::{debug, instrument, trace}; + use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 8775685e8c73b..8406e0f487626 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -19,6 +19,7 @@ use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{BytePos, Pos, Span, Symbol}; use rustc_trait_selection::traits::SelectionContext; +use tracing::debug; use super::ConstCx; use crate::errors; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index 5cd13783c2318..f0763f1e490ff 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::{symbol::sym, Span}; +use tracing::trace; use super::check::Qualifs; use super::ops::{self, NonConstOp}; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 7e8a208659b97..5949444e599a0 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, }; +use tracing::{instrument, trace}; use super::ConstCx; diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 8642dfccd7843..528274e6abac4 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -1,6 +1,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::Align; +use tracing::debug; /// Returns `true` if this place is allowed to be less aligned /// than its containing struct (because it is within a packed diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 403bc1eca1346..bc5fe39f8673a 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -5,6 +5,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Mutability}; use rustc_span::symbol::Symbol; +use tracing::trace; use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext}; use crate::interpret::*; diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index ad82c2d96e7a7..2a8f422206409 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -5,9 +5,6 @@ #![feature(type_alias_impl_trait)] #![allow(internal_features)] -#[macro_use] -extern crate tracing; - use fluent_bundle::FluentResource; use fluent_syntax::parser::ParserError; use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; @@ -20,6 +17,7 @@ use std::fmt; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use tracing::{instrument, trace}; #[cfg(not(parallel_compiler))] use std::cell::LazyCell as Lazy; diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index a805c4fcf7b97..08d4a03945489 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -68,12 +68,15 @@ pub(crate) enum KleeneOp { /// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros. #[derive(Debug, PartialEq, Encodable, Decodable)] enum TokenTree { + /// A token. Unlike `tokenstream::TokenTree::Token` this lacks a `Spacing`. + /// See the comments about `Spacing` in the `transcribe` function. Token(Token), /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS). Delimited(DelimSpan, DelimSpacing, Delimited), /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS). Sequence(DelimSpan, SequenceRepetition), - /// e.g., `$var`. + /// e.g., `$var`. The span covers the leading dollar and the ident. (The span within the ident + /// only covers the ident, e.g. `var`.) MetaVar(Span, Ident), /// e.g., `$var:expr`. Only appears on the LHS. MetaVarDecl(Span, Ident /* name to bind */, Option), diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index d3ea48e2e2a8e..8ad7cb15c92a9 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -62,7 +62,10 @@ pub(super) fn parse( match tree { TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { let span = match trees.next() { - Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => { + Some(&tokenstream::TokenTree::Token( + Token { kind: token::Colon, span: colon_span }, + _, + )) => { match trees.next() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { @@ -126,10 +129,12 @@ pub(super) fn parse( } _ => token.span, }, - tree => tree.map_or(span, tokenstream::TokenTree::span), + Some(tree) => tree.span(), + None => colon_span, } } - tree => tree.map_or(start_sp, tokenstream::TokenTree::span), + Some(tree) => tree.span(), + None => start_sp, }; result.push(TokenTree::MetaVarDecl(span, ident, None)); @@ -176,7 +181,7 @@ fn parse_tree<'a>( // Depending on what `tree` is, we could be parsing different parts of a macro match tree { // `tree` is a `$` token. Look at the next token in `trees` - &tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => { + &tokenstream::TokenTree::Token(Token { kind: token::Dollar, span: dollar_span }, _) => { // FIXME: Handle `Invisible`-delimited groups in a more systematic way // during parsing. let mut next = outer_trees.next(); @@ -209,7 +214,7 @@ fn parse_tree<'a>( err.emit(); // Returns early the same read `$` to avoid spanning // unrelated diagnostics that could be performed afterwards - return TokenTree::token(token::Dollar, span); + return TokenTree::token(token::Dollar, dollar_span); } Ok(elem) => { maybe_emit_macro_metavar_expr_feature( @@ -251,7 +256,7 @@ fn parse_tree<'a>( // special metavariable that names the crate of the invocation. Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => { let (ident, is_raw) = token.ident().unwrap(); - let span = ident.span.with_lo(span.lo()); + let span = ident.span.with_lo(dollar_span.lo()); if ident.name == kw::Crate && matches!(is_raw, IdentIsRaw::No) { TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span) } else { @@ -260,16 +265,19 @@ fn parse_tree<'a>( } // `tree` is followed by another `$`. This is an escaped `$`. - Some(&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => { + Some(&tokenstream::TokenTree::Token( + Token { kind: token::Dollar, span: dollar_span2 }, + _, + )) => { if parsing_patterns { span_dollar_dollar_or_metavar_in_the_lhs_err( sess, - &Token { kind: token::Dollar, span }, + &Token { kind: token::Dollar, span: dollar_span2 }, ); } else { - maybe_emit_macro_metavar_expr_feature(features, sess, span); + maybe_emit_macro_metavar_expr_feature(features, sess, dollar_span2); } - TokenTree::token(token::Dollar, span) + TokenTree::token(token::Dollar, dollar_span2) } // `tree` is followed by some other token. This is an error. @@ -281,7 +289,7 @@ fn parse_tree<'a>( } // There are no more tokens. Just return the `$` we already have. - None => TokenTree::token(token::Dollar, span), + None => TokenTree::token(token::Dollar, dollar_span), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 3901b82eb52ec..8a084dcb4fe3a 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -253,8 +253,23 @@ pub(super) fn transcribe<'a>( mbe::TokenTree::MetaVar(mut sp, mut original_ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. + // + // We use `Spacing::Alone` everywhere here, because that's the conservative choice + // and spacing of declarative macros is tricky. E.g. in this macro: + // ``` + // macro_rules! idents { + // ($($a:ident,)*) => { stringify!($($a)*) } + // } + // ``` + // `$a` has no whitespace after it and will be marked `JointHidden`. If you then + // call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So + // if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up + // producing "xyz", which is bad because it effectively merges tokens. + // `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid + // some of the unnecessary whitespace. let ident = MacroRulesNormalizedIdent::new(original_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { + // njn: explain the use of alone here let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 1f3547c841a90..ec7e4416b9130 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -309,10 +309,10 @@ impl ToInternal> use rustc_ast::token::*; // The code below is conservative, using `token_alone`/`Spacing::Alone` - // in most places. When the resulting code is pretty-printed by - // `print_tts` it ends up with spaces between most tokens, which is - // safe but ugly. It's hard in general to do better when working at the - // token level. + // in most places. It's hard in general to do better when working at + // the token level. When the resulting code is pretty-printed by + // `print_tts` the `space_between` function helps avoid a lot of + // unnecessary whitespace, so the results aren't too bad. let (tree, rustc) = self; match tree { TokenTree::Punct(Punct { ch, joint, span }) => { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 4540310937d02..e51f95eed021b 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::visit::walk_list; +use rustc_ast::visit::visit_opt; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -168,7 +168,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => visitor.visit_stmt(statement), } } - walk_list!(visitor, visit_expr, &blk.expr); + visit_opt!(visitor, visit_expr, &blk.expr); } visitor.cx = prev_cx; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 33c24433ca341..11a1c65b74956 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1159,7 +1159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = self .at(cause, self.param_env) .trace(prev_ty, new_ty) - .lub(DefineOpaqueTypes::No, a_sig, b_sig) + .lub(DefineOpaqueTypes::Yes, a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 8c66f239f8ee9..41caa5d4765bc 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -49,10 +49,10 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; - use std::env; use std::fs::{self, File}; use std::io::{BufWriter, Write}; +use tracing::debug; #[allow(missing_docs)] pub fn assert_dep_graph(tcx: TyCtxt<'_>) { diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 79402c88de47a..960a2d012e0fa 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -6,9 +6,6 @@ #![feature(rustdoc_internals)] #![allow(internal_features)] -#[macro_use] -extern crate tracing; - mod assert_dep_graph; mod errors; mod persist; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index e901ca36daded..2a0d681fa37ed 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -33,6 +33,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use thin_vec::ThinVec; +use tracing::debug; const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; const EXCEPT: Symbol = sym::except; diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index b459f82f23e32..303785bdb2206 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -19,6 +19,7 @@ use std::env; use std::fs; use std::io::{self, Read}; use std::path::{Path, PathBuf}; +use tracing::debug; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 193042b8cdf25..9afea3d66b0de 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -125,6 +125,7 @@ use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use rand::{thread_rng, RngCore}; +use tracing::debug; #[cfg(test)] mod tests; diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 9e6ce06678513..6c3f73cf46594 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -12,6 +12,7 @@ use rustc_session::Session; use rustc_span::ErrorGuaranteed; use std::path::{Path, PathBuf}; use std::sync::Arc; +use tracing::{debug, warn}; use super::data::*; use super::file_format; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 9777f76928095..3bf582bd26c61 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -11,6 +11,7 @@ use rustc_serialize::Encodable as RustcEncodable; use rustc_session::Session; use std::fs; use std::sync::Arc; +use tracing::debug; use super::data::*; use super::dirty_clean; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 906233ef53ec8..e230da9dfb12f 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -10,6 +10,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; use std::fs as std_fs; use std::path::Path; +use tracing::debug; /// Copies a CGU work product to the incremental compilation directory, so next compilation can /// find and reuse it. diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 8f1c4ad462a67..fbe8d31370cc3 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -104,10 +104,10 @@ infer_compare_impl_item_obligation = ...so that the definition in impl matches t infer_consider_specifying_length = consider specifying the actual array length infer_data_flows = ...but data{$label_var1_exists -> [true] {" "}from `{$label_var1}` - *[false] -> {""} + *[false] {""} } flows{$label_var2_exists -> [true] {" "}into `{$label_var2}` - *[false] -> {""} + *[false] {""} } here infer_data_lifetime_flow = ...but data with one lifetime flows into the other here diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 46a7e7b239965..e0894ed31bfc3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -173,7 +173,10 @@ pub(super) fn note_and_explain_region<'tcx>( ty::ReError(_) => return, - ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => { + // FIXME(#125431): `ReVar` shouldn't reach here. + ty::ReVar(_) => (format!("lifetime `{region}`"), alt_span), + + ty::ReBound(..) | ty::ReErased => { bug!("unexpected region for note_and_explain_region: {:?}", region); } }; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index d43be6cebcb20..5254a6576f905 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -11,7 +11,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxt, ErrorGuaranteed}; use rustc_lint::LintStore; - use rustc_middle::ty; use rustc_middle::ty::CurrentGcx; use rustc_middle::util::Providers; @@ -28,6 +27,7 @@ use rustc_span::FileName; use std::path::PathBuf; use std::result; use std::sync::Arc; +use tracing::trace; pub type Result = result::Result; diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 75df006a56f11..c1d460ddd0861 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -4,9 +4,6 @@ #![feature(thread_spawn_unchecked)] #![feature(try_blocks)] -#[macro_use] -extern crate tracing; - mod callbacks; mod errors; pub mod interface; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 76d5d7a3ac2fd..33995f80162e4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -39,6 +39,7 @@ use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; use std::sync::LazyLock; use std::{env, fs, iter}; +use tracing::{info, instrument}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { let krate = sess.time("parse_crate", || match &sess.io.input { @@ -458,7 +459,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { let source = tcx.used_crate_source(cnum); if let Some((path, _)) = &source.dylib { files.push(escape_dep_filename(&path.display().to_string())); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 987e48a1a76ff..8dac524bb5bfd 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,5 +1,4 @@ use crate::errors; -use info; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; #[cfg(parallel_compiler)] @@ -23,6 +22,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::OnceLock; use std::thread; use std::{env, iter}; +use tracing::info; /// Function pointer type that constructs a new CodegenBackend. pub type MakeBackendFn = fn() -> Box; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 6f6480a496413..a9304f27fe557 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -263,7 +263,7 @@ lint_extern_without_abi = extern declarations without an explicit ABI are deprec .help = the default ABI is {$default_abi} lint_for_loops_over_fallibles = - for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement + for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent .remove_next = to iterate over `{$recv_snip}` remove the call to `next` .use_while_let = to check pattern in a loop use `while let` @@ -627,7 +627,7 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio .label = pattern not allowed in foreign function lint_private_extern_crate_reexport = - extern crate `{$ident}` is private, and cannot be re-exported (error E0365), consider declaring with `pub` + extern crate `{$ident}` is private, and cannot be re-exported, consider declaring with `pub` lint_proc_macro_back_compat = using an old version of `{$crate_name}` .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 0f059bceae7cb..85d54ce563d2b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -70,6 +70,7 @@ use rustc_target::abi::Abi; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy}; +use tracing::debug; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -674,11 +675,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - let param_env = ty::ParamEnv::empty(); - if ty.is_copy_modulo_regions(cx.tcx, param_env) { + if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) { return; } - if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) { + if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) { return; } if def.is_variant_list_non_exhaustive() @@ -694,7 +694,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { .tcx .infer_ctxt() .build() - .type_implements_trait(iter_trait, [ty], param_env) + .type_implements_trait(iter_trait, [ty], cx.param_env) .must_apply_modulo_regions() { return; @@ -711,7 +711,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if type_allowed_to_implement_copy( cx.tcx, - param_env, + cx.param_env, ty, traits::ObligationCause::misc(item.span, item.owner_id.def_id), ) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index deeb3ae090c57..c23a67f613161 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -39,10 +39,10 @@ use rustc_span::edit_distance::find_best_match_for_names; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi; - use std::cell::Cell; use std::iter; use std::slice; +use tracing::debug; mod diagnostics; diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 236eeee615218..23c5e0a9f5fa1 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -9,6 +9,7 @@ use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan}; use rustc_middle::middle::stability; use rustc_session::lint::{BuiltinLintDiag, Lint}; use rustc_span::BytePos; +use tracing::debug; use crate::{lints, EarlyContext, LintContext as _}; diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 020ca1753cf0b..c69e680cb64fa 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -42,6 +42,22 @@ fn to_check_cfg_arg(name: Symbol, value: Option, quotes: EscapeQuotes) - } } +fn cargo_help_sub( + sess: &Session, + inst: &impl Fn(EscapeQuotes) -> String, +) -> lints::UnexpectedCfgCargoHelp { + // We don't want to suggest the `build.rs` way to expected cfgs if we are already in a + // `build.rs`. We therefor do a best effort check (looking if the `--crate-name` is + // `build_script_build`) to try to figure out if we are building a Cargo build script + + let unescaped = &inst(EscapeQuotes::No); + if matches!(&sess.opts.crate_name, Some(crate_name) if crate_name == "build_script_build") { + lints::UnexpectedCfgCargoHelp::lint_cfg(unescaped) + } else { + lints::UnexpectedCfgCargoHelp::lint_cfg_and_build_rs(unescaped, &inst(EscapeQuotes::Yes)) + } +} + pub(super) fn unexpected_cfg_name( sess: &Session, (name, name_span): (Symbol, Span), @@ -162,14 +178,7 @@ pub(super) fn unexpected_cfg_name( let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes); let invocation_help = if is_from_cargo { - let sub = if !is_feature_cfg { - Some(lints::UnexpectedCfgCargoHelp::new( - &inst(EscapeQuotes::No), - &inst(EscapeQuotes::Yes), - )) - } else { - None - }; + let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None }; lints::unexpected_cfg_name::InvocationHelp::Cargo { sub } } else { lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new( @@ -267,10 +276,7 @@ pub(super) fn unexpected_cfg_value( Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures) } } else if !is_cfg_a_well_know_name { - Some(lints::unexpected_cfg_value::CargoHelp::Other(lints::UnexpectedCfgCargoHelp::new( - &inst(EscapeQuotes::No), - &inst(EscapeQuotes::Yes), - ))) + Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst))) } else { None }; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 736c7a1106932..329221612b587 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -26,6 +26,7 @@ use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::Span; +use tracing::debug; macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index a6876d8aae793..b05f5e7638b4e 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -52,14 +52,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { let ty = cx.typeck_results().expr_ty(arg); - let &ty::Adt(adt, args) = ty.kind() else { return }; + let (adt, args, ref_mutability) = match ty.kind() { + &ty::Adt(adt, args) => (adt, args, None), + &ty::Ref(_, ty, mutability) => match ty.kind() { + &ty::Adt(adt, args) => (adt, args, Some(mutability)), + _ => return, + }, + _ => return, + }; let (article, ty, var) = match adt.did() { + did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => ("a", "Option", "Some"), did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"), did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"), _ => return, }; + let ref_prefix = match ref_mutability { + None => "", + Some(ref_mutability) => ref_mutability.ref_prefix_str(), + }; + let sub = if let Some(recv) = extract_iterator_next_call(cx, arg) && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { @@ -85,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { cx.emit_span_lint( FOR_LOOPS_OVER_FALLIBLES, arg.span, - ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion }, + ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion }, ); } } diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 2c86964feef11..5da1cbc2283b6 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::declare_lint; use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::FIRST_VARIANT; +use tracing::{debug, instrument}; use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub}; use crate::{types, LintVec}; diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 153d91ce28cb0..6e291a327fa68 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -15,6 +15,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; +use tracing::debug; declare_tool_lint! { /// The `default_hash_type` lint detects use of [`std::collections::HashMap`]/[`std::collections::HashSet`], diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index ca188277b9dee..b638ab10e11ea 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -26,9 +26,9 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::LintPass; use rustc_session::Session; use rustc_span::Span; - use std::any::Any; use std::cell::Cell; +use tracing::debug; /// Extract the [`LintStore`] from [`Session`]. /// diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 12b3d1d2f9e4f..98e321076c599 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -41,6 +41,7 @@ use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use tracing::{debug, instrument}; use crate::errors::{ MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 64fcc7e46e0e0..0ccfe23ae3726 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -39,9 +39,6 @@ #![feature(rustc_attrs)] #![allow(internal_features)] -#[macro_use] -extern crate tracing; - mod async_fn_in_trait; pub mod builtin; mod context; diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 3bd6faca37963..2f44bc4764e33 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -620,6 +620,7 @@ pub enum PtrNullChecksDiag<'a> { #[diag(lint_for_loops_over_fallibles)] pub struct ForLoopsOverFalliblesDiag<'a> { pub article: &'static str, + pub ref_prefix: &'static str, pub ty: &'static str, #[subdiagnostic] pub sub: ForLoopsOverFalliblesLoopSub<'a>, @@ -1961,21 +1962,33 @@ pub struct UnitBindingsDiag { pub struct BuiltinNamedAsmLabel; #[derive(Subdiagnostic)] -#[help(lint_unexpected_cfg_add_cargo_feature)] -#[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] -#[help(lint_unexpected_cfg_add_build_rs_println)] -pub struct UnexpectedCfgCargoHelp { - pub build_rs_println: String, - pub cargo_toml_lint_cfg: String, +pub enum UnexpectedCfgCargoHelp { + #[help(lint_unexpected_cfg_add_cargo_feature)] + #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] + LintCfg { cargo_toml_lint_cfg: String }, + #[help(lint_unexpected_cfg_add_cargo_feature)] + #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] + #[help(lint_unexpected_cfg_add_build_rs_println)] + LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String }, } impl UnexpectedCfgCargoHelp { - pub fn new(unescaped: &str, escaped: &str) -> Self { - Self { - cargo_toml_lint_cfg: format!( - "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}", - ), - build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");",), + fn cargo_toml_lint_cfg(unescaped: &str) -> String { + format!( + "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}" + ) + } + + pub fn lint_cfg(unescaped: &str) -> Self { + UnexpectedCfgCargoHelp::LintCfg { + cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), + } + } + + pub fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self { + UnexpectedCfgCargoHelp::LintCfgAndBuildRs { + cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), + build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"), } } } @@ -2227,7 +2240,7 @@ pub struct MacroUseDeprecated; pub struct UnusedMacroUse; #[derive(LintDiagnostic)] -#[diag(lint_private_extern_crate_reexport)] +#[diag(lint_private_extern_crate_reexport, code = E0365)] pub struct PrivateExternCrateReexport { pub ident: Ident, } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f9f766f832af7..9d3a838666aff 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -31,9 +31,9 @@ use rustc_span::{Span, Symbol}; use rustc_target::abi::{Abi, Size, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; - use std::iter; use std::ops::ControlFlow; +use tracing::debug; declare_lint! { /// The `unused_comparisons` lint detects comparisons made useless by diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 8866b2be07847..a6993547c8fcf 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; use std::iter; use std::ops::ControlFlow; +use tracing::instrument; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 067374c026107..3fcf3aca8afee 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1488,13 +1488,15 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, // a ThinLTO summary attached. struct LLVMRustThinLTOBuffer { std::string data; + std::string thin_link_data; }; extern "C" LLVMRustThinLTOBuffer* -LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { +LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) { auto Ret = std::make_unique(); { auto OS = raw_string_ostream(Ret->data); + auto ThinLinkOS = raw_string_ostream(Ret->thin_link_data); { if (is_thin) { PassBuilder PB; @@ -1508,7 +1510,10 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); ModulePassManager MPM; - MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); + // We only pass ThinLinkOS to be filled in if we want the summary, + // because otherwise LLVM does extra work and may double-emit some + // errors or warnings. + MPM.addPass(ThinLTOBitcodeWriterPass(OS, emit_summary ? &ThinLinkOS : nullptr)); MPM.run(*unwrap(M), MAM); } else { WriteBitcodeToFile(*unwrap(M), OS); @@ -1533,6 +1538,16 @@ LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { return Buffer->data.length(); } +extern "C" const void* +LLVMRustThinLTOBufferThinLinkDataPtr(const LLVMRustThinLTOBuffer *Buffer) { + return Buffer->thin_link_data.data(); +} + +extern "C" size_t +LLVMRustThinLTOBufferThinLinkDataLen(const LLVMRustThinLTOBuffer *Buffer) { + return Buffer->thin_link_data.length(); +} + // This is what we used to parse upstream bitcode for actual ThinLTO // processing. We'll call this once per module optimized through ThinLTO, and // it'll be called concurrently on many threads. diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 2f5dfad265c80..932603cd6b267 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -91,9 +91,6 @@ metadata_found_staticlib = found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} .help = please recompile that crate using --crate-type lib -metadata_framework_only_windows = - link kind `raw-dylib` is only supported on Windows targets - metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait @@ -233,6 +230,9 @@ metadata_profiler_builtins_needs_core = metadata_raw_dylib_no_nul = link name must not contain NUL characters if link kind is `raw-dylib` +metadata_raw_dylib_only_windows = + link kind `raw-dylib` is only supported on Windows targets + metadata_renaming_no_link = renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index be1a73ef0a7d9..44a3e9760e1e1 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -27,6 +27,7 @@ use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::{PanicStrategy, Target, TargetTriple}; +use tracing::{debug, info, trace}; use proc_macro::bridge::client::ProcMacro; use std::error::Error; diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 99181f9c8605c..bf9bbfb8cfab9 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -65,6 +65,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; +use tracing::info; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.crate_types() @@ -143,7 +144,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs) { - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -164,7 +165,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -182,7 +183,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } // Collect what we've got so far in the return vector. - let last_crate = tcx.crates(()).len(); + let last_crate = tcx.used_crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -196,7 +197,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // If the crate hasn't been included yet and it's not actually required // (e.g., it's an allocator) then we skip it here as well. - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) @@ -284,7 +285,7 @@ fn add_library( fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option { let all_crates_available_as_rlib = tcx - .crates(()) + .used_crates(()) .iter() .copied() .filter_map(|cnum| { @@ -305,7 +306,7 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index fb0010f2c5d2e..47d183a044040 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -142,8 +142,8 @@ pub struct LinkFrameworkApple { } #[derive(Diagnostic)] -#[diag(metadata_framework_only_windows, code = E0455)] -pub struct FrameworkOnlyWindows { +#[diag(metadata_raw_dylib_only_windows, code = E0455)] +pub struct RawDylibOnlyWindows { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 00bb4c435c8b6..acaf9fb0fc32a 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -20,9 +20,6 @@ extern crate proc_macro; -#[macro_use] -extern crate tracing; - pub use rmeta::provide; mod dependency_format; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 6ff19974c1e79..73443de355383 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -231,6 +231,7 @@ use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; +use tracing::{debug, info}; use snap::read::FrameDecoder; use std::borrow::Cow; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 58760be921a61..1254ebead0727 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -151,7 +151,7 @@ impl<'tcx> Collector<'tcx> { } "raw-dylib" => { if !sess.target.is_like_windows { - sess.dcx().emit_err(errors::FrameworkOnlyWindows { span }); + sess.dcx().emit_err(errors::RawDylibOnlyWindows { span }); } NativeLibKind::RawDylib } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index f91e121a240ed..695525e755de9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -28,6 +28,7 @@ use rustc_session::cstore::{CrateSource, ExternCrate}; use rustc_session::Session; use rustc_span::symbol::kw; use rustc_span::{BytePos, Pos, SpanData, SpanDecoder, SyntaxContext, DUMMY_SP}; +use tracing::debug; use proc_macro::bridge::client::ProcMacro; use std::iter::TrustedLen; diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index c783149a69514..4cad317ce80cd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -435,7 +435,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // traversal, but not globally minimal across all crates. let bfs_queue = &mut VecDeque::new(); - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { // Ignore crates without a corresponding local `extern crate` item. if tcx.missing_extern_crate_item(cnum) { continue; @@ -505,7 +505,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| { + crates_including_speculative: |tcx, ()| { // The list of loaded crates is now frozen in query cache, // so make sure cstore is not mutably accessed from here on. tcx.untracked().cstore.freeze(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index db0dc6d9064b7..4587a4315e3c6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -33,6 +33,7 @@ use std::collections::hash_map::Entry; use std::fs::File; use std::io::{Read, Seek, Write}; use std::path::{Path, PathBuf}; +use tracing::{debug, instrument, trace}; pub(super) struct EncodeContext<'a, 'tcx> { opaque: opaque::FileEncoder, @@ -1898,7 +1899,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let deps = self .tcx - .crates(()) + .crates_including_speculative(()) .iter() .map(|&cnum| { let dep = CrateDep { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 019cb91c765ea..23a6ceb4d3e5d 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -2,6 +2,7 @@ use crate::rmeta::*; use rustc_hir::def::CtorOf; use rustc_index::Idx; +use tracing::trace; pub(super) trait IsDefault: Default { fn is_default(&self) -> bool; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index f3f24f7717701..b17af47fbcd4f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1016,7 +1016,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { let krate = tcx.hir_crate(()); let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash"); - let upstream_crates = upstream_crates(tcx); + let upstream_crates = upstream_crates_for_hashing(tcx); let resolutions = tcx.resolutions(()); @@ -1085,9 +1085,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { Svh::new(crate_hash) } -fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { +fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { let mut upstream_crates: Vec<_> = tcx - .crates(()) + .crates_including_speculative(()) .iter() .map(|&cnum| { let stable_crate_id = tcx.stable_crate_id(cnum); diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index d35b9fc46e4dd..bf10a71dbaec1 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefPathHash}; use rustc_session::StableCrateId; use rustc_span::def_id::{CrateNum, LocalDefId}; use rustc_span::{ExpnHash, ExpnId, DUMMY_SP}; +use tracing::instrument; macro_rules! declare_hooks { ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 70437fdcb6ff1..d47e393c912ad 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -63,9 +63,6 @@ #![feature(yeet_expr)] // tidy-alphabetical-end -#[macro_use] -extern crate tracing; - #[cfg(test)] mod tests; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 086582e60a3c0..d82d23d62afad 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -12,6 +12,7 @@ use rustc_session::lint::{ use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP}; +use tracing::instrument; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index de07ba9700ac1..6e89dc494fa56 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -13,6 +13,7 @@ use rustc_hir as hir; use rustc_hir::{HirId, HirIdMap, Node}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::{Span, DUMMY_SP}; +use tracing::debug; use std::fmt; use std::ops::Deref; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index e5df05763b022..a377e35b2e9e0 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -23,6 +23,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use std::num::NonZero; +use tracing::debug; #[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index e974279f1917c..4e37295a571bd 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -3,12 +3,12 @@ use std::cmp; +use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance}; use rustc_data_structures::sorted_map::SortedMap; use rustc_macros::HashStable; -use rustc_target::abi::{HasDataLayout, Size}; - -use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use rustc_target::abi::{HasDataLayout, Size}; +use tracing::trace; /// Stores the provenance information of pointers stored in memory. #[derive(Clone, PartialEq, Eq, Hash, Debug)] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 6e152cbcb6571..eabbcc2033f1f 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -1,19 +1,22 @@ -use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; +use std::borrow::Cow; +use std::{any::Any, backtrace::Backtrace, fmt}; -use crate::error; -use crate::mir::{ConstAlloc, ConstValue}; -use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree}; +use either::Either; use rustc_ast_ir::Mutability; use rustc_data_structures::sync::Lock; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_session::CtfeBacktrace; +use rustc_span::Symbol; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange}; -use std::borrow::Cow; -use std::{any::Any, backtrace::Backtrace, fmt}; +use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; + +use crate::error; +use crate::mir::{ConstAlloc, ConstValue}; +use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum ErrorHandled { @@ -63,6 +66,9 @@ impl ReportedErrorInfo { pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo { ReportedErrorInfo { is_tainted_by_errors: true, error } } + pub fn is_tainted_by_errors(&self) -> bool { + self.is_tainted_by_errors + } } impl From for ReportedErrorInfo { @@ -310,6 +316,10 @@ pub enum UndefinedBehaviorInfo<'tcx> { RemainderOverflow, /// Overflowing inbounds pointer arithmetic. PointerArithOverflow, + /// Overflow in arithmetic that may not overflow. + ArithOverflow { intrinsic: Symbol }, + /// Shift by too much. + ShiftOverflow { intrinsic: Symbol, shift_amount: Either }, /// Invalid metadata in a wide pointer InvalidMeta(InvalidMetaKind), /// Reading a C string that does not end within its allocation. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 739b1410e6db4..16093cfca6add 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -15,6 +15,7 @@ use std::num::NonZero; use std::sync::atomic::{AtomicU32, Ordering}; use smallvec::{smallvec, SmallVec}; +use tracing::{debug, trace}; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashMap; diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 04d6301116eea..a85181954696d 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -9,6 +9,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; +use tracing::{debug, instrument}; impl<'tcx> TyCtxt<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 25cc9ac47c83a..2b2b9392a7093 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -37,6 +37,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use either::Either; +use tracing::trace; use std::borrow::Cow; use std::cell::RefCell; diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index daab6c855819b..a3d2140eb1b11 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -18,6 +18,7 @@ use rustc_span::symbol::Symbol; use rustc_span::Span; use std::fmt; use std::hash::Hash; +use tracing::debug; /// Describes how a monomorphization will be instantiated in object files. #[derive(PartialEq)] diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 334122970178e..18c48d99b81ce 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -1,4 +1,5 @@ use rustc_middle::mir::*; +use tracing::debug; /// This struct represents a patch to MIR, which can add /// new statements and basic blocks and patch over block diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 7e8598b49df43..7bfb4ac867aa7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -15,6 +15,7 @@ use rustc_middle::mir::interpret::{ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_target::abi::Size; +use tracing::trace; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index c421c937dc36d..a122cffdb876a 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -5,6 +5,7 @@ use crate::mir::*; use rustc_hir as hir; +use tracing::{debug, instrument}; #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct PlaceTy<'tcx> { @@ -297,9 +298,11 @@ impl BorrowKind { impl BinOp { pub(crate) fn to_hir_binop(self) -> hir::BinOpKind { match self { - BinOp::Add => hir::BinOpKind::Add, - BinOp::Sub => hir::BinOpKind::Sub, - BinOp::Mul => hir::BinOpKind::Mul, + // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending + // on whether overflow checks are enabled or not. + BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add, + BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub, + BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul, BinOp::Div => hir::BinOpKind::Div, BinOp::Rem => hir::BinOpKind::Rem, BinOp::BitXor => hir::BinOpKind::BitXor, @@ -313,10 +316,8 @@ impl BinOp { BinOp::Gt => hir::BinOpKind::Gt, BinOp::Le => hir::BinOpKind::Le, BinOp::Ge => hir::BinOpKind::Ge, + // We don't have HIR syntax for these. BinOp::Cmp - | BinOp::AddWithOverflow - | BinOp::SubWithOverflow - | BinOp::MulWithOverflow | BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked @@ -338,6 +339,11 @@ impl BinOp { }) } + /// Returns whether this is a `FooWithOverflow` + pub fn is_overflowing(self) -> bool { + self.overflowing_to_wrapping().is_some() + } + /// If this is a `Foo`, return `Some(FooWithOverflow)`. pub fn wrapping_to_overflowing(self) -> Option { Some(match self { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c2f7a227f6661..5a6decc4f9497 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -780,7 +780,7 @@ rustc_queries! { separate_provide_extern } - /// Maps from a trait item to the trait item "descriptor". + /// Maps from a trait/impl item to the trait/impl item "descriptor". query associated_item(key: DefId) -> ty::AssocItem { desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -1860,13 +1860,22 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } - query crates(_: ()) -> &'tcx [CrateNum] { + /// All loaded crates, including those loaded purely for doc links or diagnostics. + /// (Diagnostics include lints, so speculatively loaded crates may occur in successful + /// compilation even without doc links.) + /// Should be used when encoding crate metadata (and therefore when generating crate hash, + /// depinfo and similar things), to avoid dangling crate references in other encoded data, + /// like source maps. + /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some + /// items from it as well. + /// But otherwise, `used_crates` should generally be used. + query crates_including_speculative(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } - // Crates that are loaded non-speculatively (not for diagnostics or doc links). - // FIXME: This is currently only used for collecting lang items, but should be used instead of - // `crates` in most other cases too. + /// Crates that are loaded non-speculatively (not for diagnostics or doc links). + /// Should be used to maintain observable language behavior, for example when collecting lang + /// items or impls from all crates, or collecting libraries to link. query used_crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index c68b7a6c9eb39..454897aa67207 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -32,6 +32,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use std::cmp::Ordering; use std::fmt; use std::ops::Index; +use tracing::instrument; pub mod visit; diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e28e4d66fafc8..f30270abd5c1e 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -1,6 +1,7 @@ use crate::ty::error::TypeError; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; use crate::ty::{self, InferConst, Ty, TyCtxt}; +use tracing::{debug, instrument}; /// A type "A" *matches* "B" if the fresh types in B could be /// instantiated with values so as to make it equal to A. Matching is diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 77da3fbe1d799..48193754077d0 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -17,6 +17,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT}; +use tracing::{debug, info, trace}; use std::cell::RefCell; use std::hash::{Hash, Hasher}; diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index f7cc055be11c2..40a0dbeb2c222 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -8,6 +8,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; +use tracing::{debug, instrument}; mod int; mod kind; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 896114e2483c7..6e53b5bb52067 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -74,6 +74,7 @@ use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; +use tracing::{debug, instrument}; use std::assert_matches::assert_matches; use std::borrow::Borrow; @@ -1611,7 +1612,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_traits(self) -> impl Iterator + 'tcx { iter::once(LOCAL_CRATE) - .chain(self.crates(()).iter().copied()) + .chain(self.used_crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) } diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index cfd36fd8c7c35..cd6e7df31f7cd 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -1,6 +1,7 @@ use crate::query::Providers; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; +use tracing::debug; pub(super) fn provide(providers: &mut Providers) { *providers = Providers { erase_regions_ty, ..*providers }; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index fd3bee16e2685..d432aeada2c88 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1,6 +1,7 @@ use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; +use tracing::{debug, instrument}; pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index cb11bb3ef16d3..c7b15c64b0869 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -18,6 +18,7 @@ use rustc_macros::{ use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; +use tracing::debug; use core::intrinsics; use std::marker::PhantomData; diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index cfaca05c2f06b..870e4865aeab1 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; +use tracing::instrument; use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index ef7a7a99ff7e9..efcf428c2136f 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas use rustc_query_system::ich::StableHashingContext; use std::cell::RefCell; use std::ptr; +use tracing::trace; impl<'a, 'tcx, H, T> HashStable> for &'tcx ty::list::RawList where diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index e3eea83ba49ad..54b8507babfa9 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -1,5 +1,6 @@ use rustc_macros::HashStable; use smallvec::SmallVec; +use tracing::instrument; use crate::ty::context::TyCtxt; use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty}; diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index da5d57db5bef9..afdf2cbc72667 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -48,6 +48,7 @@ use crate::ty::context::TyCtxt; use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility}; use rustc_type_ir::TyKind::*; +use tracing::instrument; pub mod inhabited_predicate; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index a08fde976bc1a..7da7f69a9543b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -14,6 +14,7 @@ use rustc_macros::{ use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Symbol; +use tracing::{debug, instrument}; use std::assert_matches::assert_matches; use std::fmt; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cf701f837d895..60ce87440328b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -19,6 +19,7 @@ use rustc_target::abi::*; use rustc_target::spec::{ abi::Abi as SpecAbi, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi, }; +use tracing::debug; use std::borrow::Cow; use std::cmp; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f27409894fa59..79cfeb71d47e4 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -61,6 +61,7 @@ use rustc_span::{ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx}; +use tracing::{debug, instrument}; pub use vtable::*; use std::assert_matches::assert_matches; diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 115cf3eeb226c..e2cfabfdafaa4 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -11,6 +11,7 @@ use crate::traits::query::NoSolution; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use tracing::{debug, instrument}; #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] pub enum NormalizationError<'tcx> { diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index fa5265c58e430..bbcbcdce1b2ec 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -5,6 +5,7 @@ use crate::ty::{GenericArg, GenericArgKind}; use rustc_data_structures::fx::FxHashMap; use rustc_span::def_id::DefId; use rustc_span::Span; +use tracing::{debug, instrument, trace}; /// Converts generic params of a TypeFoldable from one /// item's generics to another. Usually from a function's generics diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 293cc0a7eca3e..efb6cf2554625 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -4,6 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{extension, HashStable}; use rustc_type_ir as ir; use std::cmp::Ordering; +use tracing::instrument; use crate::ty::{ self, DebruijnIndex, EarlyBinder, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index dc77f59f3d0fa..3c27df9529aa1 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -7,6 +7,7 @@ use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use tracing::{debug, instrument, trace}; // `pretty` is a separate module only for organization. mod pretty; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a1ead1bb59f54..0bcd02aaa3acf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3258,7 +3258,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let queue = &mut Vec::new(); let mut seen_defs: DefIdSet = Default::default(); - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.crates_including_speculative(()).iter() { let def_id = cnum.as_def_id(); // Ignore crates that are not direct dependencies. diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index d7da37385e1fc..958e7e401684b 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -8,6 +8,7 @@ use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use rustc_type_ir::RegionKind as IrRegionKind; pub use rustc_type_ir::RegionVid; use std::ops::Deref; +use tracing::debug; use crate::ty::{self, BoundVar, TyCtxt, TypeFlags}; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 947de3f3aaa50..f02b4849f83dd 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -14,6 +14,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::TypeVisitable; use rustc_target::spec::abi; use std::iter; +use tracing::{debug, instrument}; use super::Pattern; diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index cb2f7284eaa0d..8ec7946e71801 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -2,6 +2,7 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree}; use rustc_hir as hir; use rustc_hir::ItemLocalMap; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use tracing::debug; /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index cf1cbb934105b..37a34f283387e 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -5,6 +5,7 @@ use hir::def_id::LOCAL_CRATE; use rustc_hir as hir; use rustc_hir::def_id::DefId; use std::iter; +use tracing::debug; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; @@ -205,7 +206,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. if !trait_id.is_local() { - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { for &(impl_def_id, simplified_self_ty) in tcx.implementations_of_trait((cnum, trait_id)).iter() { @@ -247,7 +248,7 @@ pub(super) fn incoherent_impls_provider( let mut impls = Vec::new(); let mut res = Ok(()); - for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { + for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) { let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { Ok(impls) => impls, Err(e) => { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8c14f1e080a14..5a3d90221ebd8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -24,6 +24,7 @@ use rustc_target::abi::{Float, Integer, IntegerType, Size}; use rustc_target::spec::abi::Abi; use smallvec::{smallvec, SmallVec}; use std::{fmt, iter}; +use tracing::{debug, instrument, trace}; #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 089e61749c3e8..a9421aacff839 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -5,6 +5,7 @@ use crate::ty::{self, Ty}; use crate::ty::{GenericArg, GenericArgKind}; use rustc_data_structures::sso::SsoHashSet; use smallvec::{smallvec, SmallVec}; +use tracing::debug; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index 4e2a2c6ae0acc..a4cbfe867112d 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{lang_items, LangItem}; use rustc_span::symbol::Ident; use rustc_span::{sym, DesugaringKind, Span}; +use tracing::debug; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CallDesugaringKind { diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 0ca4fce5da9b1..027e2703e98d6 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -3,6 +3,7 @@ use crate::ty::GenericArgsRef; use crate::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::source_map::Spanned; +use tracing::debug; /// Checks if the specified `local` is used as the `self` parameter of a method call /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 0bb44dbb8706b..67e1e15defab4 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -335,12 +335,12 @@ mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133) + borrow of layout constrained field with interior mutability is unsafe and requires unsafe block .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values .label = borrow of layout constrained field with interior mutability mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> [1] feature *[count] features @@ -355,48 +355,47 @@ mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = .label = call to function with `#[target_feature]` mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = - call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133) + call to unsafe function `{$function}` is unsafe and requires unsafe block .note = consult the function's documentation for information on how to avoid undefined behavior .label = call to unsafe function mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless = - call to unsafe function is unsafe and requires unsafe block (error E0133) + call to unsafe function is unsafe and requires unsafe block .note = consult the function's documentation for information on how to avoid undefined behavior .label = call to unsafe function mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe = - dereference of raw pointer is unsafe and requires unsafe block (error E0133) + dereference of raw pointer is unsafe and requires unsafe block .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior .label = dereference of raw pointer mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe = - use of extern static is unsafe and requires unsafe block (error E0133) + use of extern static is unsafe and requires unsafe block .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior .label = use of extern static mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe - block (error E0133) + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = - use of inline assembly is unsafe and requires unsafe block (error E0133) + use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior .label = use of inline assembly mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe = - use of mutable static is unsafe and requires unsafe block (error E0133) + use of mutable static is unsafe and requires unsafe block .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior .label = use of mutable static mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe = - mutation of layout constrained field is unsafe and requires unsafe block (error E0133) + mutation of layout constrained field is unsafe and requires unsafe block .note = mutating layout constrained fields cannot statically be checked for valid values .label = mutation of layout constrained field mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe = - access to union field is unsafe and requires unsafe block (error E0133) + access to union field is unsafe and requires unsafe block .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior .label = access to union field diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6ae98e15946d7..c1d645aa42cb8 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -5,6 +5,7 @@ use rustc_middle::span_bug; use rustc_middle::thir::*; use rustc_middle::{mir::*, ty}; use rustc_span::Span; +use tracing::debug; impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn ast_block( diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index 18e45291e9a86..6034c8fadc57f 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -3,6 +3,7 @@ use crate::build::CFG; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use tracing::debug; impl<'tcx> CFG<'tcx> { pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 0384b9bc154e2..8bcd429b67eb2 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -38,7 +38,7 @@ macro_rules! parse_by_kind { ) => {{ let expr_id = $self.preparse($expr_id); let expr = &$self.thir[expr_id]; - debug!("Trying to parse {:?} as {}", expr.kind, $expected); + tracing::debug!("Trying to parse {:?} as {}", expr.kind, $expected); let $expr_name = expr; match &expr.kind { $( diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 817f5f787b1b1..b4dd423f344ab 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -11,6 +11,7 @@ use rustc_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_target::abi::Size; +use tracing::{instrument, trace}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 076ee7f85ff68..09ce134a2bf6c 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -5,6 +5,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary}; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::*; +use tracing::{debug, instrument}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an operand suitable for use until the end of the current diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 9963629fc52f7..93d0d4e59ba99 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::AdtDef; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance}; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; +use tracing::{debug, instrument, trace}; use std::assert_matches::assert_matches; use std::iter; diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 60a2827a3e292..9f9b566bb8fa3 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::cast::{mir_cast_kind, CastTy}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, UpvarArgs}; use rustc_span::{Span, DUMMY_SP}; +use tracing::debug; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an rvalue suitable for use until the end of the current diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 27e66e7f54d0a..607c7c3259c18 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -6,6 +6,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::*; +use tracing::{debug, instrument}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr` into a fresh temporary. This is used when building diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index f8c910730456c..9349133d2dbc1 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -12,6 +12,7 @@ use rustc_middle::thir::*; use rustc_middle::ty::CanonicalUserTypeAnnotation; use rustc_span::source_map::Spanned; use std::iter; +use tracing::{debug, instrument}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 7f5e45e20cc17..2bdeb579a02de 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -3,6 +3,7 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::*; +use tracing::debug; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Builds a block of MIR statements to evaluate the THIR `expr`. diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 3fc719394bf9e..5413878936983 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -20,6 +20,8 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty}; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Pos, Span}; use rustc_target::abi::VariantIdx; +use tracing::{debug, instrument}; + // helper functions, broken out by category: mod simplify; mod test; @@ -925,7 +927,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for subpattern in prefix.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } - for subpattern in slice { + if let Some(subpattern) = slice { self.visit_primary_bindings( subpattern, pattern_user_ty.clone().subslice(from, to), diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 90f12e55ff4c7..543301c71a0ec 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -14,6 +14,7 @@ use crate::build::matches::{MatchPair, PatternExtraData, TestCase}; use crate::build::Builder; +use tracing::{debug, instrument}; use std::mem; diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index f3faeb4158eef..2040071e76eb2 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -18,6 +18,7 @@ use rustc_span::def_id::DefId; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use tracing::{debug, instrument}; use std::cmp::Ordering; diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 14c74c761ebb3..770f689724af0 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -7,6 +7,7 @@ use rustc_middle::thir::{self, *}; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; +use tracing::debug; impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn field_match_pairs<'pat>( diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index c263de79c3b84..04e6d24e5a172 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; +use tracing::debug; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Adds a new temporary value of type `ty` storing the result of diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index be32363fec528..c7850c7aea872 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -94,6 +94,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::lint::Level; use rustc_span::source_map::Spanned; use rustc_span::{Span, DUMMY_SP}; +use tracing::{debug, instrument}; #[derive(Debug)] pub struct Scopes<'tcx> { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e2a28467b8457..38e6c00add81e 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -21,7 +21,7 @@ pub struct UnconditionalRecursion { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { #[label] @@ -32,7 +32,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] @@ -42,7 +42,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] @@ -52,7 +52,7 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] @@ -62,7 +62,7 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] @@ -72,7 +72,7 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] @@ -82,7 +82,7 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] @@ -92,7 +92,7 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)] #[note] pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] @@ -102,7 +102,10 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)] +#[diag( + mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe, + code = E0133 +)] #[note] pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] @@ -112,7 +115,10 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)] +#[diag( + mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe, + code = E0133, +)] pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, @@ -121,7 +127,7 @@ pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)] #[help] pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { #[label] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 2e1cb0e1b5e05..74600c6b12eb7 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -10,9 +10,6 @@ #![feature(let_chains)] #![feature(try_blocks)] -#[macro_use] -extern crate tracing; - mod build; mod check_unsafety; mod errors; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 03c7c1fd6ec60..31bc72184caa7 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,6 +2,7 @@ use rustc_ast as ast; use rustc_middle::bug; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; +use tracing::trace; use crate::build::parse_float_into_scalar; diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index d4a347975dbae..54eafdd828ae6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -1,12 +1,12 @@ use crate::thir::cx::Cx; use rustc_hir as hir; +use rustc_index::Idx; use rustc_middle::middle::region; use rustc_middle::thir::*; use rustc_middle::ty; - -use rustc_index::Idx; use rustc_middle::ty::CanonicalUserTypeAnnotation; +use tracing::debug; impl<'tcx> Cx<'tcx> { pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b77666669605d..28f9300b97a88 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -25,6 +25,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::source_map::Spanned; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; +use tracing::{debug, info, instrument, trace}; impl<'tcx> Cx<'tcx> { pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index d1d21f88aef6a..3c0e2521d88fe 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -17,6 +17,7 @@ use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; +use tracing::instrument; pub(crate) fn thir_body( tcx: TyCtxt<'_>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 592f0dcf4ef55..30f57c8c622f7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -24,6 +24,7 @@ use rustc_session::lint::builtin::{ }; use rustc_span::hygiene::DesugaringKind; use rustc_span::{sym, Span}; +use tracing::instrument; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let typeck_results = tcx.typeck(def_id); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index c6f81c3cb9976..bac47fafbfd7b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -12,6 +12,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause}; +use tracing::{debug, instrument, trace}; use std::cell::Cell; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index dc845b3d4acc5..7408c679f00b1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -25,6 +25,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; use rustc_target::abi::{FieldIdx, Integer}; +use tracing::{debug, instrument}; use std::cmp::Ordering; diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index 340eb3c2eea0f..53a2a0852eb49 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -1,6 +1,7 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType}; +use tracing::debug; pub(crate) trait UserAnnotatedTyHelpers<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index de1ca8d823b3e..82c59d7d9595c 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -1,6 +1,7 @@ use crate::elaborate_drops::DropFlagState; use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind}; use rustc_target::abi::VariantIdx; +use tracing::debug; use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex}; use super::MoveDataParamEnv; diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 185e87baed8cf..bdc59e843563b 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -11,6 +11,7 @@ use rustc_span::source_map::Spanned; use rustc_span::DUMMY_SP; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::{fmt, iter}; +use tracing::{debug, instrument}; /// The value of an inserted drop flag. #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index ea9cf6565e7c8..564a99e5df81b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -19,6 +19,7 @@ use rustc_middle::mir::{create_dump_file, dump_enabled}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; +use tracing::{debug, error}; use super::fmt::DebugWithContext; use super::graphviz; diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 180168c731686..f0b79dab0c974 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -3,6 +3,7 @@ use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges}; use rustc_middle::ty::{self, TyCtxt}; +use tracing::{debug, instrument}; use crate::drop_flag_effects_for_function_entry; use crate::drop_flag_effects_for_location; diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 5e96a73f6c53f..0b397a67d45cb 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,9 +4,6 @@ #![feature(let_chains)] #![feature(try_blocks)] -#[macro_use] -extern crate tracing; - use rustc_middle::ty; // Please change the public `use` directives cautiously, as they might be used by external tools. diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 521ecb1b9a594..1fb77bef3d410 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -4,6 +4,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use smallvec::{smallvec, SmallVec}; +use tracing::debug; use std::mem; diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index d7e3c91b875f8..1de9055273b73 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -18,6 +18,7 @@ use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use tracing::{debug, info}; pub struct SanityCheck; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 1e5322dd99b8a..5e2d88f94ca28 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -45,6 +45,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::{FieldIdx, VariantIdx}; +use tracing::debug; use crate::lattice::{HasBottom, HasTop}; use crate::{ diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 3d24a56cdd7c6..53a016f01ecef 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -165,9 +165,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } } } - Rvalue::BinaryOp(overflowing_op, box (left, right)) - if let Some(op) = overflowing_op.overflowing_to_wrapping() => - { + Rvalue::BinaryOp(op, box (left, right)) if op.is_overflowing() => { // Flood everything now, so we can use `insert_value_idx` directly later. state.flood(target.as_ref(), self.map()); @@ -177,7 +175,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into())); if value_target.is_some() || overflow_target.is_some() { - let (val, overflow) = self.binary_op(state, op, left, right); + let (val, overflow) = self.binary_op(state, *op, left, right); if let Some(value_target) = value_target { // We have flooded `target` earlier. @@ -186,7 +184,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { if let Some(overflow_target) = overflow_target { let overflow = match overflow { FlatSet::Top => FlatSet::Top, - FlatSet::Elem(overflow) => FlatSet::Elem(Scalar::from_bool(overflow)), + FlatSet::Elem(overflow) => FlatSet::Elem(overflow), FlatSet::Bottom => FlatSet::Bottom, }; // We have flooded `target` earlier. @@ -266,15 +264,16 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { FlatSet::Top => FlatSet::Top, } } - Rvalue::BinaryOp(op, box (left, right)) => { + Rvalue::BinaryOp(op, box (left, right)) if !op.is_overflowing() => { // Overflows must be ignored here. + // The overflowing operators are handled in `handle_assign`. let (val, _overflow) = self.binary_op(state, *op, left, right); val } Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { FlatSet::Elem(value) => self .ecx - .wrapping_unary_op(*op, &value) + .unary_op(*op, &value) .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)), FlatSet::Bottom => FlatSet::Bottom, FlatSet::Top => FlatSet::Top, @@ -439,7 +438,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { op: BinOp, left: &Operand<'tcx>, right: &Operand<'tcx>, - ) -> (FlatSet, FlatSet) { + ) -> (FlatSet, FlatSet) { let left = self.eval_operand(left, state); let right = self.eval_operand(right, state); @@ -447,9 +446,17 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom), // Both sides are known, do the actual computation. (FlatSet::Elem(left), FlatSet::Elem(right)) => { - match self.ecx.overflowing_binary_op(op, &left, &right) { - Ok((val, overflow)) => { - (FlatSet::Elem(val.to_scalar()), FlatSet::Elem(overflow)) + match self.ecx.binary_op(op, &left, &right) { + // Ideally this would return an Immediate, since it's sometimes + // a pair and sometimes not. But as a hack we always return a pair + // and just make the 2nd component `Bottom` when it does not exist. + Ok(val) => { + if matches!(val.layout.abi, Abi::ScalarPair(..)) { + let (val, overflow) = val.to_scalar_pair(); + (FlatSet::Elem(val), FlatSet::Elem(overflow)) + } else { + (FlatSet::Elem(val.to_scalar()), FlatSet::Bottom) + } } _ => (FlatSet::Top, FlatSet::Top), } @@ -475,7 +482,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { (FlatSet::Elem(arg_scalar), FlatSet::Bottom) } BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => { - (FlatSet::Elem(arg_scalar), FlatSet::Elem(false)) + (FlatSet::Elem(arg_scalar), FlatSet::Elem(Scalar::from_bool(false))) } _ => (FlatSet::Top, FlatSet::Top), } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 1f3e407180b5f..9d2e7153eb569 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -223,7 +223,7 @@ enum Value<'tcx> { NullaryOp(NullOp<'tcx>, Ty<'tcx>), UnaryOp(UnOp, VnIndex), BinaryOp(BinOp, VnIndex, VnIndex), - CheckedBinaryOp(BinOp, VnIndex, VnIndex), + CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead Cast { kind: CastKind, value: VnIndex, @@ -497,7 +497,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { UnaryOp(un_op, operand) => { let operand = self.evaluated[operand].as_ref()?; let operand = self.ecx.read_immediate(operand).ok()?; - let (val, _) = self.ecx.overflowing_unary_op(un_op, &operand).ok()?; + let val = self.ecx.unary_op(un_op, &operand).ok()?; val.into() } BinaryOp(bin_op, lhs, rhs) => { @@ -505,7 +505,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let lhs = self.ecx.read_immediate(lhs).ok()?; let rhs = self.evaluated[rhs].as_ref()?; let rhs = self.ecx.read_immediate(rhs).ok()?; - let (val, _) = self.ecx.overflowing_binary_op(bin_op, &lhs, &rhs).ok()?; + let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?; val.into() } CheckedBinaryOp(bin_op, lhs, rhs) => { @@ -513,14 +513,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let lhs = self.ecx.read_immediate(lhs).ok()?; let rhs = self.evaluated[rhs].as_ref()?; let rhs = self.ecx.read_immediate(rhs).ok()?; - let (val, overflowed) = self.ecx.overflowing_binary_op(bin_op, &lhs, &rhs).ok()?; - let tuple = Ty::new_tup_from_iter( - self.tcx, - [val.layout.ty, self.tcx.types.bool].into_iter(), - ); - let tuple = self.ecx.layout_of(tuple).ok()?; - ImmTy::from_scalar_pair(val.to_scalar(), Scalar::from_bool(overflowed), tuple) - .into() + let val = self + .ecx + .binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs) + .ok()?; + val.into() } Cast { kind, value, from: _, to } => match kind { CastKind::IntToInt | CastKind::IntToFloat => { diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 38fc37a3a3131..0fa5c1b912612 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -304,20 +304,25 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>, location: Location) -> Option<()> { let arg = self.eval_operand(arg)?; - if let (val, true) = self.use_ecx(|this| { - let val = this.ecx.read_immediate(&arg)?; - let (_res, overflow) = this.ecx.overflowing_unary_op(op, &val)?; - Ok((val, overflow)) - })? { - // `AssertKind` only has an `OverflowNeg` variant, so make sure that is - // appropriate to use. - assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - self.report_assert_as_lint( - location, - AssertLintKind::ArithmeticOverflow, - AssertKind::OverflowNeg(val.to_const_int()), - ); - return None; + // The only operator that can overflow is `Neg`. + if op == UnOp::Neg && arg.layout.ty.is_integral() { + // Compute this as `0 - arg` so we can use `SubWithOverflow` to check for overflow. + let (arg, overflow) = self.use_ecx(|this| { + let arg = this.ecx.read_immediate(&arg)?; + let (_res, overflow) = this + .ecx + .binary_op(BinOp::SubWithOverflow, &ImmTy::from_int(0, arg.layout), &arg)? + .to_scalar_pair(); + Ok((arg, overflow.to_bool()?)) + })?; + if overflow { + self.report_assert_as_lint( + location, + AssertLintKind::ArithmeticOverflow, + AssertKind::OverflowNeg(arg.to_const_int()), + ); + return None; + } } Some(()) @@ -363,11 +368,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - if let (Some(l), Some(r)) = (l, r) { - // The remaining operators are handled through `overflowing_binary_op`. + // Div/Rem are handled via the assertions they trigger. + // But for Add/Sub/Mul, those assertions only exist in debug builds, and we want to + // lint in release builds as well, so we check on the operation instead. + // So normalize to the "overflowing" operator, and then ensure that it + // actually is an overflowing operator. + let op = op.wrapping_to_overflowing().unwrap_or(op); + // The remaining operators are handled through `wrapping_to_overflowing`. + if let (Some(l), Some(r)) = (l, r) + && l.layout.ty.is_integral() + && op.is_overflowing() + { if self.use_ecx(|this| { - let (_res, overflow) = this.ecx.overflowing_binary_op(op, &l, &r)?; - Ok(overflow) + let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair(); + overflow.to_bool() })? { self.report_assert_as_lint( location, @@ -399,8 +413,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } Rvalue::BinaryOp(op, box (left, right)) => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - let op = op.overflowing_to_wrapping().unwrap_or(*op); - self.check_binary_op(op, left, right, location)?; + self.check_binary_op(*op, left, right, location)?; } // Do not try creating references (#67862) @@ -547,17 +560,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let right = self.eval_operand(right)?; let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?; - if let Some(bin_op) = bin_op.overflowing_to_wrapping() { - let (val, overflowed) = - self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?; - let overflowed = ImmTy::from_bool(overflowed, self.tcx); + let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?; + if matches!(val.layout.abi, Abi::ScalarPair(..)) { + // FIXME `Value` should properly support pairs in `Immediate`... but currently it does not. + let (val, overflow) = val.to_pair(&self.ecx); Value::Aggregate { variant: VariantIdx::ZERO, - fields: [Value::from(val), overflowed.into()].into_iter().collect(), + fields: [val.into(), overflow.into()].into_iter().collect(), } } else { - let val = - self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?; val.into() } } @@ -566,7 +577,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let operand = self.eval_operand(operand)?; let val = self.use_ecx(|this| this.ecx.read_immediate(&operand))?; - let val = self.use_ecx(|this| this.ecx.wrapping_unary_op(un_op, &val))?; + let val = self.use_ecx(|this| this.ecx.unary_op(un_op, &val))?; val.into() } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4b435649216b9..76972ff2263d8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -236,6 +236,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::Size; use std::path::PathBuf; +use tracing::{debug, instrument, trace}; use crate::errors::{ self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit, TypeLengthLimit, diff --git a/compiler/rustc_monomorphize/src/collector/move_check.rs b/compiler/rustc_monomorphize/src/collector/move_check.rs index 4cc7275ab8069..851f86e86b8e8 100644 --- a/compiler/rustc_monomorphize/src/collector/move_check.rs +++ b/compiler/rustc_monomorphize/src/collector/move_check.rs @@ -1,4 +1,5 @@ use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; +use tracing::debug; use super::*; use crate::errors::LargeAssignmentsLint; diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index ddfb42a6f4a6c..b298fe5813f8f 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -2,9 +2,6 @@ #![feature(is_sorted)] #![allow(rustc::potential_query_instability)] -#[macro_use] -extern crate tracing; - use rustc_hir::lang_items::LangItem; use rustc_middle::bug; use rustc_middle::query::{Providers, TyCtxtAt}; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 8f7b4c6472c90..21d52004728a2 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -116,6 +116,7 @@ use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt}; use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_session::CodegenUnits; use rustc_span::symbol::Symbol; +use tracing::debug; use crate::collector::UsageMap; use crate::collector::{self, MonoItemCollectionStrategy}; diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 14ebe27ac23c5..dc13766d14512 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::{ GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, }; use rustc_span::symbol::sym; +use tracing::{debug, instrument}; use crate::errors::UnusedGenericParamsHint; diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 6eb8bed6a8c4e..d3a6a0339784a 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -18,6 +18,7 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; use rustc_span::{edition::Edition, BytePos, Pos, Span}; +use tracing::debug; mod diagnostics; mod tokentrees; diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index fa242a32a1814..cad25c66827b9 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -6,6 +6,7 @@ use std::ops::Range; use rustc_errors::{Applicability, DiagCtxt, ErrorGuaranteed}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; +use tracing::debug; use crate::errors::{MoreThanOneCharNote, MoreThanOneCharSugg, NoBraceUnicodeSub, UnescapeError}; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 0f973dfcd7969..322739be3fb3c 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -10,9 +10,6 @@ #![feature(iter_intersperse)] #![feature(let_chains)] -#[macro_use] -extern crate tracing; - use rustc_ast as ast; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ac12787f2ef05..9677eea060449 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -45,6 +45,7 @@ use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP}; use std::mem::take; use std::ops::{Deref, DerefMut}; use thin_vec::{thin_vec, ThinVec}; +use tracing::{debug, trace}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index fd3f63a04de55..1b99bc015b608 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -36,6 +36,7 @@ use rustc_span::source_map::{self, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; +use tracing::instrument; /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f43ddadc2ea02..53757c38e8b04 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -23,6 +23,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::fmt::Write; use std::mem; use thin_vec::{thin_vec, ThinVec}; +use tracing::debug; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1924533e28049..4fe84b91b8b16 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -39,6 +39,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; use std::cell::Cell; use std::collections::hash_map::Entry; +use tracing::debug; #[derive(LintDiagnostic)] #[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)] diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 906ecdfe5abae..78653e5f95a6d 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -82,7 +82,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems { let mut items = DiagnosticItems::default(); // Collect diagnostic items in other crates. - for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { + for &cnum in tcx.crates_including_speculative(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id { collect_item(tcx, &mut items, name, def_id); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 180552785fe75..7fdd9924b513e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1100,7 +1100,7 @@ pub struct BreakInsideCoroutine<'a> { pub struct OutsideLoop<'a> { #[primary_span] #[label] - pub span: Span, + pub spans: Vec, pub name: &'a str, pub is_break: bool, #[subdiagnostic] @@ -1112,7 +1112,7 @@ pub struct OutsideLoopSuggestion { #[suggestion_part(code = "'block: ")] pub block_span: Span, #[suggestion_part(code = " 'block")] - pub break_span: Span, + pub break_spans: Vec, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index d3608759eec70..045a0a1525bfa 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,9 +12,6 @@ #![feature(map_try_insert)] #![feature(try_blocks)] -#[macro_use] -extern crate tracing; - use rustc_middle::query::Providers; pub mod abi_test; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index b50cb158b1fed..b0a753604e2e3 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -99,10 +99,10 @@ use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{BytePos, Span}; - use std::io; use std::io::prelude::*; use std::rc::Rc; +use tracing::{debug, instrument}; mod rwu_table; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 3b20112eab7b9..2587a18b8c897 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; +use std::fmt; use Context::*; use rustc_hir as hir; @@ -25,22 +27,55 @@ enum Context { Closure(Span), Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource }, UnlabeledBlock(Span), + UnlabeledIfBlock(Span), LabeledBlock, Constant, } -#[derive(Copy, Clone)] +#[derive(Clone)] +struct BlockInfo { + name: String, + spans: Vec, + suggs: Vec, +} + +#[derive(PartialEq)] +enum BreakContextKind { + Break, + Continue, +} + +impl fmt::Display for BreakContextKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + BreakContextKind::Break => "break", + BreakContextKind::Continue => "continue", + } + .fmt(f) + } +} + +#[derive(Clone)] struct CheckLoopVisitor<'a, 'tcx> { sess: &'a Session, tcx: TyCtxt<'tcx>, - cx: Context, + // Keep track of a stack of contexts, so that suggestions + // are not made for contexts where it would be incorrect, + // such as adding a label for an `if`. + // e.g. `if 'foo: {}` would be incorrect. + cx_stack: Vec, + block_breaks: BTreeMap, } fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - tcx.hir().visit_item_likes_in_module( - module_def_id, - &mut CheckLoopVisitor { sess: tcx.sess, tcx, cx: Normal }, - ); + let mut check = CheckLoopVisitor { + sess: tcx.sess, + tcx, + cx_stack: vec![Normal], + block_breaks: Default::default(), + }; + tcx.hir().visit_item_likes_in_module(module_def_id, &mut check); + check.report_outside_loop_error(); } pub(crate) fn provide(providers: &mut Providers) { @@ -83,6 +118,45 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { match e.kind { + hir::ExprKind::If(cond, then, else_opt) => { + self.visit_expr(cond); + + let get_block = |ck_loop: &CheckLoopVisitor<'a, 'hir>, + expr: &hir::Expr<'hir>| + -> Option<&hir::Block<'hir>> { + if let hir::ExprKind::Block(b, None) = expr.kind + && matches!( + ck_loop.cx_stack.last(), + Some(&Normal) + | Some(&Constant) + | Some(&UnlabeledBlock(_)) + | Some(&UnlabeledIfBlock(_)) + ) + { + Some(b) + } else { + None + } + }; + + if let Some(b) = get_block(self, then) { + self.with_context(UnlabeledIfBlock(b.span.shrink_to_lo()), |v| { + v.visit_block(b) + }); + } else { + self.visit_expr(then); + } + + if let Some(else_expr) = else_opt { + if let Some(b) = get_block(self, else_expr) { + self.with_context(UnlabeledIfBlock(b.span.shrink_to_lo()), |v| { + v.visit_block(b) + }); + } else { + self.visit_expr(else_expr); + } + } + } hir::ExprKind::Loop(ref b, _, source, _) => { self.with_context(Loop(source), |v| v.visit_block(b)); } @@ -101,11 +175,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(b)); } - hir::ExprKind::Block(ref b, None) if matches!(self.cx, Fn) => { + hir::ExprKind::Block(ref b, None) if matches!(self.cx_stack.last(), Some(&Fn)) => { self.with_context(Normal, |v| v.visit_block(b)); } hir::ExprKind::Block(ref b, None) - if matches!(self.cx, Normal | Constant | UnlabeledBlock(_)) => + if matches!( + self.cx_stack.last(), + Some(&Normal) | Some(&Constant) | Some(&UnlabeledBlock(_)) + ) => { self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b)); } @@ -178,7 +255,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Some(label) => sp_lo.with_hi(label.ident.span.hi()), None => sp_lo.shrink_to_lo(), }; - self.require_break_cx("break", e.span, label_sp); + self.require_break_cx( + BreakContextKind::Break, + e.span, + label_sp, + self.cx_stack.len() - 1, + ); } hir::ExprKind::Continue(destination) => { self.require_label_in_labeled_block(e.span, &destination, "continue"); @@ -200,7 +282,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } Err(_) => {} } - self.require_break_cx("continue", e.span, e.span) + self.require_break_cx( + BreakContextKind::Continue, + e.span, + e.span, + self.cx_stack.len() - 1, + ) } _ => intravisit::walk_expr(self, e), } @@ -212,18 +299,26 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { where F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>), { - let old_cx = self.cx; - self.cx = cx; + self.cx_stack.push(cx); f(self); - self.cx = old_cx; + self.cx_stack.pop(); } - fn require_break_cx(&self, name: &str, span: Span, break_span: Span) { - let is_break = name == "break"; - match self.cx { + fn require_break_cx( + &mut self, + br_cx_kind: BreakContextKind, + span: Span, + break_span: Span, + cx_pos: usize, + ) { + match self.cx_stack[cx_pos] { LabeledBlock | Loop(_) => {} Closure(closure_span) => { - self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name }); + self.sess.dcx().emit_err(BreakInsideClosure { + span, + closure_span, + name: &br_cx_kind.to_string(), + }); } Coroutine { coroutine_span, kind, source } => { let kind = match kind { @@ -239,17 +334,32 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.sess.dcx().emit_err(BreakInsideCoroutine { span, coroutine_span, - name, + name: &br_cx_kind.to_string(), kind, source, }); } - UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => { - let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); - self.sess.dcx().emit_err(OutsideLoop { span, name, is_break, suggestion }); + UnlabeledBlock(block_span) + if br_cx_kind == BreakContextKind::Break && block_span.eq_ctxt(break_span) => + { + let block = self.block_breaks.entry(block_span).or_insert_with(|| BlockInfo { + name: br_cx_kind.to_string(), + spans: vec![], + suggs: vec![], + }); + block.spans.push(span); + block.suggs.push(break_span); + } + UnlabeledIfBlock(_) if br_cx_kind == BreakContextKind::Break => { + self.require_break_cx(br_cx_kind, span, break_span, cx_pos - 1); } - Normal | Constant | Fn | UnlabeledBlock(_) => { - self.sess.dcx().emit_err(OutsideLoop { span, name, is_break, suggestion: None }); + Normal | Constant | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) => { + self.sess.dcx().emit_err(OutsideLoop { + spans: vec![span], + name: &br_cx_kind.to_string(), + is_break: br_cx_kind == BreakContextKind::Break, + suggestion: None, + }); } } } @@ -261,7 +371,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { cf_type: &str, ) -> bool { if !span.is_desugaring(DesugaringKind::QuestionMark) - && self.cx == LabeledBlock + && self.cx_stack.last() == Some(&LabeledBlock) && label.label.is_none() { self.sess.dcx().emit_err(UnlabeledInLabeledBlock { span, cf_type }); @@ -269,4 +379,18 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { } false } + + fn report_outside_loop_error(&mut self) { + for (s, block) in &self.block_breaks { + self.sess.dcx().emit_err(OutsideLoop { + spans: block.spans.clone(), + name: &block.name, + is_break: true, + suggestion: Some(OutsideLoopSuggestion { + block_span: *s, + break_spans: block.suggs.clone(), + }), + }); + } + } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 55b7c6dce4d9b..ab1dd2485566e 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -37,6 +37,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt}; use rustc_privacy::DefIdVisitor; use rustc_session::config::CrateType; +use tracing::debug; /// Determines whether this item is recursive for reachability. See `is_recursively_reachable_local` /// below for details. diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 05c833cdfb657..31c709f2eb68a 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -25,9 +25,9 @@ use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPR use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; - use std::mem::replace; use std::num::NonZero; +use tracing::{debug, info}; #[derive(PartialEq)] enum AnnotationKind { @@ -1020,7 +1020,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // stabilization diagnostic, but it can be avoided when there are no // `remaining_lib_features`. let mut all_implications = remaining_implications.clone(); - for &cnum in tcx.crates(()) { + for &cnum in tcx.used_crates(()) { all_implications .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v))); } @@ -1033,7 +1033,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { &all_implications, ); - for &cnum in tcx.crates(()) { + for &cnum in tcx.used_crates(()) { if remaining_lib_features.is_empty() && remaining_implications.is_empty() { break; } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 90691ca17908b..d80addf12364d 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { } let mut missing = FxHashSet::default(); - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d1d0e336cfe05..63d0d6c260dbe 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,7 +12,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey}; @@ -3280,7 +3280,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_local(&mut self, local: &'ast Local) { debug!("resolving local ({:?})", local); // Resolve the type. - walk_list!(self, visit_ty, &local.ty); + visit_opt!(self, visit_ty, &local.ty); // Resolve the initializer. if let Some((init, els)) = local.kind.init_else_opt() { @@ -3479,8 +3479,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_arm(&mut self, arm: &'ast Arm) { self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(&arm.pat, PatternSource::Match); - walk_list!(this, visit_expr, &arm.guard); - walk_list!(this, visit_expr, &arm.body); + visit_opt!(this, visit_expr, &arm.guard); + visit_opt!(this, visit_expr, &arm.body); }); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7dd9fdf60f934..5ac4d194e8721 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -465,6 +465,7 @@ impl FromStr for SplitDwarfKind { #[derive(Encodable, Decodable)] pub enum OutputType { Bitcode, + ThinLinkBitcode, Assembly, LlvmAssembly, Mir, @@ -492,6 +493,7 @@ impl OutputType { match *self { OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true, OutputType::Bitcode + | OutputType::ThinLinkBitcode | OutputType::Assembly | OutputType::LlvmAssembly | OutputType::Mir @@ -502,6 +504,7 @@ impl OutputType { pub fn shorthand(&self) -> &'static str { match *self { OutputType::Bitcode => "llvm-bc", + OutputType::ThinLinkBitcode => "thin-link-bitcode", OutputType::Assembly => "asm", OutputType::LlvmAssembly => "llvm-ir", OutputType::Mir => "mir", @@ -518,6 +521,7 @@ impl OutputType { "llvm-ir" => OutputType::LlvmAssembly, "mir" => OutputType::Mir, "llvm-bc" => OutputType::Bitcode, + "thin-link-bitcode" => OutputType::ThinLinkBitcode, "obj" => OutputType::Object, "metadata" => OutputType::Metadata, "link" => OutputType::Exe, @@ -528,8 +532,9 @@ impl OutputType { fn shorthands_display() -> String { format!( - "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", + "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", OutputType::Bitcode.shorthand(), + OutputType::ThinLinkBitcode.shorthand(), OutputType::Assembly.shorthand(), OutputType::LlvmAssembly.shorthand(), OutputType::Mir.shorthand(), @@ -543,6 +548,7 @@ impl OutputType { pub fn extension(&self) -> &'static str { match *self { OutputType::Bitcode => "bc", + OutputType::ThinLinkBitcode => "indexing.o", OutputType::Assembly => "s", OutputType::LlvmAssembly => "ll", OutputType::Mir => "mir", @@ -559,9 +565,11 @@ impl OutputType { | OutputType::LlvmAssembly | OutputType::Mir | OutputType::DepInfo => true, - OutputType::Bitcode | OutputType::Object | OutputType::Metadata | OutputType::Exe => { - false - } + OutputType::Bitcode + | OutputType::ThinLinkBitcode + | OutputType::Object + | OutputType::Metadata + | OutputType::Exe => false, } } } @@ -644,6 +652,7 @@ impl OutputTypes { pub fn should_codegen(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode + | OutputType::ThinLinkBitcode | OutputType::Assembly | OutputType::LlvmAssembly | OutputType::Mir @@ -657,6 +666,7 @@ impl OutputTypes { pub fn should_link(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode + | OutputType::ThinLinkBitcode | OutputType::Assembly | OutputType::LlvmAssembly | OutputType::Mir @@ -1769,6 +1779,12 @@ fn parse_output_types( display = OutputType::shorthands_display(), )) }); + if output_type == OutputType::ThinLinkBitcode && !unstable_opts.unstable_options { + early_dcx.early_fatal(format!( + "{} requested but -Zunstable-options not specified", + OutputType::ThinLinkBitcode.shorthand() + )); + } output_types.insert(output_type, path); } } diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index f4e2436efb9fb..9cb8cd836e6bf 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -51,6 +51,14 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")]) } +/// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is +/// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools, +/// etc. +pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf { + let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple); + PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")]) +} + #[cfg(unix)] fn current_dll_path() -> Result { use std::ffi::{CStr, OsStr}; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a2872fc1661af..a5cf136db6a62 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -449,15 +449,24 @@ impl Session { ) } - /// Returns a list of directories where target-specific tool binaries are located. + /// Returns a list of directories where target-specific tool binaries are located. Some fallback + /// directories are also returned, for example if `--sysroot` is used but tools are missing + /// (#125246): we also add the bin directories to the sysroot where rustc is located. pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { - let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, config::host_triple()); - let p = PathBuf::from_iter([ - Path::new(&self.sysroot), - Path::new(&rustlib_path), - Path::new("bin"), - ]); - if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } + let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple()); + let fallback_sysroot_paths = filesearch::sysroot_candidates() + .into_iter() + .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple())); + let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths); + + if self_contained { + // The self-contained tools are expected to be e.g. in `bin/self-contained` in the + // sysroot's `rustlib` path, so we add such a subfolder to the bin path, and the + // fallback paths. + search_paths.flat_map(|path| [path.clone(), path.join("self-contained")]).collect() + } else { + search_paths.collect() + } } pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fd31c020f899a..7afe46f2cbe1c 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -23,8 +23,8 @@ use stable_mir::mir::{BinOp, Body, Place}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, - ForeignItemKind, GenericArgs, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, UintTy, - VariantDef, + ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, + UintTy, VariantDef, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; use std::cell::RefCell; @@ -126,7 +126,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; iter::once(LOCAL_CRATE) - .chain(tables.tcx.crates(()).iter().copied()) + .chain(tables.tcx.used_crates(()).iter().copied()) .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter()) .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() @@ -201,14 +201,19 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn external_crates(&self) -> Vec { let tables = self.0.borrow(); - tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() + tables + .tcx + .used_crates(()) + .iter() + .map(|crate_num| smir_crate(tables.tcx, *crate_num)) + .collect() } fn find_crates(&self, name: &str) -> Vec { let tables = self.0.borrow(); let crates: Vec = [LOCAL_CRATE] .iter() - .chain(tables.tcx.crates(()).iter()) + .chain(tables.tcx.used_crates(()).iter()) .filter_map(|crate_num| { let crate_name = tables.tcx.crate_name(*crate_num).to_string(); (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) @@ -307,6 +312,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> { sig.stable(&mut *tables) } + fn intrinsic(&self, def: DefId) -> Option { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = def.internal(&mut *tables, tcx); + let intrinsic = tcx.intrinsic_raw(def_id); + intrinsic.map(|_| IntrinsicDef(def)) + } + + fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + tcx.intrinsic(def_id).unwrap().name.to_string() + } + + fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + tcx.intrinsic_raw(def_id).unwrap().must_be_overridden + } + fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; @@ -645,16 +672,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } } - /// Retrieve the plain intrinsic name of an instance. - /// - /// This assumes that the instance is an intrinsic. - fn intrinsic_name(&self, def: InstanceDef) -> Symbol { - let tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - let intrinsic = tables.tcx.intrinsic(instance.def_id()).unwrap(); - intrinsic.name.to_string() - } - fn ty_layout(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 9090bb30f897e..6f513f24948a5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -14,6 +14,7 @@ use rustc_target::abi::call::{ }; use rustc_target::abi::*; use rustc_target::spec::abi::Abi as SpecAbi; +use tracing::debug; use std::iter; diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index b40a0d0a58e4a..67ffb8a58b5ad 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -11,6 +11,7 @@ use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt}; use rustc_middle::{mir, thir}; use rustc_span::Span; use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; +use tracing::{debug, instrument}; use std::iter; diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 41f482d8a7068..0d089205c1ec9 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; +use tracing::debug; use traits::{translate_args, Reveal}; use crate::errors::UnexpectedFnPtrAssociatedItem; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 1ef22497a8fc5..1dee14fae57e3 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -16,6 +16,7 @@ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; use rustc_target::abi::*; +use tracing::{debug, instrument, trace}; use std::fmt::Debug; use std::iter; diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index e8c5c54d3a09c..bd89265d94264 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -16,9 +16,6 @@ #![feature(let_chains)] #![feature(never_type)] -#[macro_use] -extern crate tracing; - use rustc_middle::query::Providers; mod abi; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 4e23fb3038365..72ee1a4824953 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; use rustc_session::Limit; use rustc_span::sym; +use tracing::debug; use crate::errors::NeedsDropOverflow; diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index be227ec8b9aa1..ccc522053a659 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; +use tracing::{instrument, trace}; use crate::errors::{DuplicateArg, NotParam}; diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 2d8c78267d9fc..97a1b94263e90 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -8,6 +8,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; +use tracing::{instrument, trace}; pub trait SpannedTypeVisitor<'tcx> { type Result: VisitorResult = (); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 3094956fa5f34..617e8a5436569 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, Upcast}; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits; +use tracing::{debug, instrument}; #[instrument(level = "debug", skip(tcx), ret)] fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option> { diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 231d9ba49a39c..4dd64228bbadb 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -13,8 +13,8 @@ use crate::target::MachineInfo; use crate::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, - ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyKind, - UintTy, VariantDef, + ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, + TyKind, UintTy, VariantDef, }; use crate::{ mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, @@ -88,6 +88,16 @@ pub trait Context { /// Retrieve the function signature for the given generic arguments. fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; + /// Retrieve the intrinsic definition if the item corresponds one. + fn intrinsic(&self, item: DefId) -> Option; + + /// Retrieve the plain function name of an intrinsic. + fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol; + + /// Returns whether the intrinsic has no meaningful body and all backends + /// need to shim all calls to it. + fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool; + /// Retrieve the closure signature for the given generic arguments. fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig; @@ -198,7 +208,6 @@ pub trait Context { fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option; fn krate(&self, def_id: DefId) -> Crate; fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; - fn intrinsic_name(&self, def: InstanceDef) -> Symbol; /// Return information about the target machine. fn target_info(&self) -> MachineInfo; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 394038926f61a..572f1499c5a5c 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -106,7 +106,9 @@ impl Instance { /// which is more convenient to match with intrinsic symbols. pub fn intrinsic_name(&self) -> Option { match self.kind { - InstanceKind::Intrinsic => Some(with(|context| context.intrinsic_name(self.def))), + InstanceKind::Intrinsic => { + Some(with(|context| context.intrinsic(self.def.def_id()).unwrap().fn_name())) + } InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None, } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 321c56b623a25..f3ac2bfcdb01f 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -621,6 +621,41 @@ impl FnDef { pub fn body(&self) -> Option { with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) } + + /// Get the information of the intrinsic if this function is a definition of one. + pub fn as_intrinsic(&self) -> Option { + with(|cx| cx.intrinsic(self.def_id())) + } + + /// Check if the function is an intrinsic. + #[inline] + pub fn is_intrinsic(&self) -> bool { + self.as_intrinsic().is_some() + } +} + +crate_def! { + pub IntrinsicDef; +} + +impl IntrinsicDef { + /// Returns the plain name of the intrinsic. + /// e.g., `transmute` for `core::intrinsics::transmute`. + pub fn fn_name(&self) -> Symbol { + with(|cx| cx.intrinsic_name(*self)) + } + + /// Returns whether the intrinsic has no meaningful body and all backends + /// need to shim all calls to it. + pub fn must_be_overridden(&self) -> bool { + with(|cx| cx.intrinsic_must_be_overridden(*self)) + } +} + +impl From for FnDef { + fn from(def: IntrinsicDef) -> Self { + FnDef(def.0) + } } crate_def! { diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index daf2612833ddc..0c2642341235b 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -46,6 +46,8 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', - # This matches `EXTRA_CHECK_CFGS` in `src/bootstrap/src/lib.rs`. + # core use #[path] imports to portable-simd `core_simd` crate + # and to stdarch `core_arch` crate which messes-up with Cargo list + # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', ] diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9b372eac52455..60a27863413cc 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -340,7 +340,9 @@ impl<'a> Arguments<'a> { #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] pub const fn new_const(pieces: &'a [&'static str]) -> Self { if pieces.len() > 1 { - panic!("invalid args"); + // Since panic!() expands to panic_fmt(format_args!()), using panic! here is both a + // bit silly and also significantly increases the amount of MIR generated by panics. + crate::panicking::panic_nounwind("invalid args"); } Arguments { pieces, fmt: None, args: &[] } } @@ -350,7 +352,8 @@ impl<'a> Arguments<'a> { #[inline] pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> { if pieces.len() < args.len() || pieces.len() > args.len() + 1 { - panic!("invalid args"); + // See Arguments::new_const for why we don't use panic!. + crate::panicking::panic_nounwind("invalid args"); } Arguments { pieces, fmt: None, args } } diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index bf53b2245ac59..d3a4d6aff2d8b 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -80,47 +80,6 @@ macro_rules! forward_ref_op_assign { } } -/// Create a zero-size type similar to a closure type, but named. -macro_rules! impl_fn_for_zst { - ($( - $( #[$attr: meta] )* - struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = - |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty - $body: block; - )+) => { - $( - $( #[$attr] )* - struct $Name; - - impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name { - #[inline] - extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { - $body - } - } - - impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name { - #[inline] - extern "rust-call" fn call_mut( - &mut self, - ($( $arg, )*): ($( $ArgTy, )*) - ) -> $ReturnTy { - Fn::call(&*self, ($( $arg, )*)) - } - } - - impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name { - type Output = $ReturnTy; - - #[inline] - extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy { - Fn::call(&self, ($( $arg, )*)) - } - } - )+ - } -} - /// A macro for defining `#[cfg]` if-else statements. /// /// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dcf68b36c7a2e..206d1ab885291 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -255,6 +255,7 @@ #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] +#![feature(type_alias_impl_trait)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 8ad045275adec..19c91ba2eb988 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -108,7 +108,7 @@ impl [u8] { without modifying the original"] #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] pub fn escape_ascii(&self) -> EscapeAscii<'_> { - EscapeAscii { inner: self.iter().flat_map(EscapeByte) } + EscapeAscii { inner: self.iter().flat_map(|byte| byte.escape_ascii()) } } /// Returns a byte slice with leading ASCII whitespace bytes removed. @@ -190,12 +190,7 @@ impl [u8] { } } -impl_fn_for_zst! { - #[derive(Clone)] - struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault { - ascii::escape_default(*byte) - }; -} +type EscapeByte = impl (Fn(&u8) -> ascii::EscapeDefault) + Copy; /// An iterator over the escaped version of a byte slice. /// diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 19627f28e64f8..d61f04102e5e5 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1274,8 +1274,10 @@ pub struct SplitWhitespace<'a> { #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[derive(Clone, Debug)] pub struct SplitAsciiWhitespace<'a> { - pub(super) inner: - Map, BytesIsNotEmpty>, UnsafeBytesToStr>, + pub(super) inner: Map< + Filter, BytesIsNotEmpty<'a>>, + UnsafeBytesToStr<'a>, + >, } /// An iterator over the substrings of a string, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 669cdc92e3586..edda4d1b68703 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -983,7 +983,7 @@ impl str { #[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")] #[inline] pub fn split_whitespace(&self) -> SplitWhitespace<'_> { - SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) } + SplitWhitespace { inner: self.split(char::is_whitespace).filter(|s| !s.is_empty()) } } /// Splits a string slice by ASCII whitespace. @@ -1032,8 +1032,13 @@ impl str { #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[inline] pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> { - let inner = - self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr); + let inner = self + .as_bytes() + .split(u8::is_ascii_whitespace) + .filter(|s| !s.is_empty()) + // SAFETY: the byte slice came from a string and was only split + // along character boundaries, so the resulting slices are strings. + .map(|bytes| unsafe { from_utf8_unchecked(bytes) }); SplitAsciiWhitespace { inner } } @@ -1085,7 +1090,11 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn lines(&self) -> Lines<'_> { - Lines(self.split_inclusive('\n').map(LinesMap)) + Lines(self.split_inclusive('\n').map(|line| { + let Some(line) = line.strip_suffix('\n') else { return line }; + let Some(line) = line.strip_suffix('\r') else { return line }; + line + })) } /// An iterator over the lines of a string. @@ -2636,14 +2645,19 @@ impl str { #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_debug(&self) -> EscapeDebug<'_> { let mut chars = self.chars(); - EscapeDebug { - inner: chars - .next() - .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)) - .into_iter() - .flatten() - .chain(chars.flat_map(CharEscapeDebugContinue)), - } + let first = chars + .next() + .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)) + .into_iter() + .flatten(); + let inner = first.chain(chars.flat_map(|c| { + c.escape_debug_ext(EscapeDebugExtArgs { + escape_grapheme_extended: false, + escape_single_quote: true, + escape_double_quote: true, + }) + })); + EscapeDebug { inner } } /// Return an iterator that escapes each char in `self` with [`char::escape_default`]. @@ -2681,7 +2695,7 @@ impl str { without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_default(&self) -> EscapeDefault<'_> { - EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } + EscapeDefault { inner: self.chars().flat_map(char::escape_default) } } /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`]. @@ -2719,7 +2733,7 @@ impl str { without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_unicode(&self) -> EscapeUnicode<'_> { - EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } + EscapeUnicode { inner: self.chars().flat_map(char::escape_unicode) } } } @@ -2750,59 +2764,15 @@ impl Default for &mut str { } } -impl_fn_for_zst! { - /// A nameable, cloneable fn type - #[derive(Clone)] - struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str { - let Some(line) = line.strip_suffix('\n') else { return line }; - let Some(line) = line.strip_suffix('\r') else { return line }; - line - }; - - #[derive(Clone)] - struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { - c.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: false, - escape_single_quote: true, - escape_double_quote: true - }) - }; - - #[derive(Clone)] - struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode { - c.escape_unicode() - }; - #[derive(Clone)] - struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault { - c.escape_default() - }; - - #[derive(Clone)] - struct IsWhitespace impl Fn = |c: char| -> bool { - c.is_whitespace() - }; - - #[derive(Clone)] - struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool { - byte.is_ascii_whitespace() - }; - - #[derive(Clone)] - struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool { - !s.is_empty() - }; - - #[derive(Clone)] - struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool { - !s.is_empty() - }; - - #[derive(Clone)] - struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str { - // SAFETY: not safe - unsafe { from_utf8_unchecked(bytes) } - }; -} +type LinesMap = impl (Fn(&str) -> &str) + Copy; +type CharEscapeDebugContinue = impl (FnMut(char) -> char::EscapeDebug) + Copy; +type CharEscapeUnicode = impl (Fn(char) -> char::EscapeUnicode) + Copy; +type CharEscapeDefault = impl (Fn(char) -> char::EscapeDefault) + Copy; +type IsWhitespace = impl (Fn(char) -> bool) + Copy; +type IsAsciiWhitespace = impl (Fn(&u8) -> bool) + Copy; +type IsNotEmpty = impl (Fn(&&str) -> bool) + Copy; +type BytesIsNotEmpty<'a> = impl (FnMut(&&'a [u8]) -> bool) + Copy; +type UnsafeBytesToStr<'a> = impl (FnMut(&'a [u8]) -> &'a str) + Copy; // This is required to make `impl From<&str> for Box` and `impl From for Box` not overlap. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 7691721b91e21..3d21b09fa8a02 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -5,6 +5,7 @@ use crate::mem::transmute; use crate::any::Any; use crate::fmt; use crate::marker::PhantomData; +use crate::panic::AssertUnwindSafe; use crate::ptr; /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] @@ -236,7 +237,7 @@ enum ExtData<'a> { pub struct Context<'a> { waker: &'a Waker, local_waker: &'a LocalWaker, - ext: ExtData<'a>, + ext: AssertUnwindSafe>, // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes // are contravariant while return-position lifetimes are @@ -279,7 +280,9 @@ impl<'a> Context<'a> { #[unstable(feature = "context_ext", issue = "123392")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn ext(&mut self) -> &mut dyn Any { - match &mut self.ext { + // FIXME: this field makes Context extra-weird about unwind safety + // can we justify AssertUnwindSafe if we stabilize this? do we care? + match &mut *self.ext { ExtData::Some(data) => *data, ExtData::None(unit) => unit, } @@ -353,7 +356,7 @@ impl<'a> ContextBuilder<'a> { #[rustc_const_unstable(feature = "const_waker", issue = "102012")] #[unstable(feature = "context_ext", issue = "123392")] pub const fn from(cx: &'a mut Context<'_>) -> Self { - let ext = match &mut cx.ext { + let ext = match &mut *cx.ext { ExtData::Some(ext) => ExtData::Some(*ext), ExtData::None(()) => ExtData::None(()), }; @@ -396,7 +399,7 @@ impl<'a> ContextBuilder<'a> { #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; - Context { waker, local_waker, ext, _marker, _marker2 } + Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } } } diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index a47ef7aa1ebc6..00a6fd75b4f46 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -170,6 +170,7 @@ pub fn test_iter() { } #[test] +#[allow(for_loops_over_fallibles)] pub fn test_iter_mut() { let mut ok: Result = Ok(100); for loc in ok.iter_mut() { diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 23ae2e7dc0ded..3d7d36b27e53b 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -815,6 +815,18 @@ pub enum Delimiter { /// "macro variable" `$var`. It is important to preserve operator priorities in cases like /// `$var * 3` where `$var` is `1 + 2`. /// Invisible delimiters might not survive roundtrip of a token stream through a string. + /// + ///
+ /// + /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output + /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input + /// of a proc_macro macro are preserved, and only in very specific circumstances. + /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve + /// operator priorities as indicated above. The other `Delimiter` variants should be used + /// instead in this context. This is a rustc bug. For details, see + /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062). + /// + ///
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] None, } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 4b8ee4c130918..e56f03808b311 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -100,10 +100,14 @@ test = true [lints.rust.unexpected_cfgs] level = "warn" +# x.py uses beta cargo, so `check-cfg` entries do not yet take effect +# for rust-lang/rust. But for users of `-Zbuild-std` it does. +# The unused warning is waiting for rust-lang/cargo#13925 to reach beta. check-cfg = [ 'cfg(bootstrap)', - 'cfg(backtrace_in_libstd)', - 'cfg(netbsd10)', 'cfg(target_arch, values("xtensa"))', - 'cfg(feature, values("std", "as_crate"))', + # std use #[path] imports to portable-simd `std_float` crate + # and to the `backtrace` crate which messes-up with Cargo list + # of declared features, we therefor expect any feature cfg + 'cfg(feature, values(any()))', ] diff --git a/library/std/build.rs b/library/std/build.rs index 7a47b52e8e4eb..7d975df545ecf 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -7,9 +7,13 @@ fn main() { let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); + + println!("cargo:rustc-check-cfg=cfg(netbsd10)"); if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() { println!("cargo:rustc-cfg=netbsd10"); } + + println!("cargo:rustc-check-cfg=cfg(restricted_std)"); if target_os == "linux" || target_os == "android" || target_os == "netbsd" @@ -59,8 +63,11 @@ fn main() { // - arch=avr // - JSON targets // - Any new targets that have not been explicitly added above. - println!("cargo:rustc-cfg=feature=\"restricted-std\""); + println!("cargo:rustc-cfg=restricted_std"); } - println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + + println!("cargo:rustc-check-cfg=cfg(backtrace_in_libstd)"); println!("cargo:rustc-cfg=backtrace_in_libstd"); + + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 949c543a26479..4a18db3d5a3fc 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -213,9 +213,9 @@ //! [array]: prim@array //! [slice]: prim@slice -#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] +#![cfg_attr(not(restricted_std), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr( - feature = "restricted-std", + restricted_std, unstable( feature = "restricted_std", issue = "none", diff --git a/library/std/src/sys/thread_local/fast_local.rs b/library/std/src/sys/thread_local/fast_local.rs deleted file mode 100644 index 49b51a729e428..0000000000000 --- a/library/std/src/sys/thread_local/fast_local.rs +++ /dev/null @@ -1,247 +0,0 @@ -use super::lazy::LazyKeyInner; -use crate::cell::Cell; -use crate::sys::thread_local_dtor::register_dtor; -use crate::{fmt, mem, panic, ptr}; - -#[doc(hidden)] -#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] -#[allow_internal_unsafe] -#[unstable(feature = "thread_local_internals", issue = "none")] -#[rustc_macro_transparency = "semitransparent"] -pub macro thread_local_inner { - // used to generate the `LocalKey` value for const-initialized thread locals - (@key $t:ty, const $init:expr) => {{ - #[inline] - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - _init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - const INIT_EXPR: $t = $init; - // If the platform has support for `#[thread_local]`, use it. - #[thread_local] - // We use `UnsafeCell` here instead of `static mut` to ensure any generated TLS shims - // have a nonnull attribute on their return value. - static VAL: $crate::cell::UnsafeCell<$t> = $crate::cell::UnsafeCell::new(INIT_EXPR); - - // If a dtor isn't needed we can do something "very raw" and - // just get going. - if !$crate::mem::needs_drop::<$t>() { - unsafe { - return $crate::option::Option::Some(&*VAL.get()) - } - } - - // 0 == dtor not registered - // 1 == dtor registered, dtor not run - // 2 == dtor registered and is running or has run - #[thread_local] - static STATE: $crate::cell::Cell<$crate::primitive::u8> = $crate::cell::Cell::new(0); - - // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires - // all that comes with it. - unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) { - $crate::thread::local_impl::abort_on_dtor_unwind(|| { - let old_state = STATE.replace(2); - $crate::debug_assert_eq!(old_state, 1); - // Safety: safety requirement is passed on to caller. - unsafe { $crate::ptr::drop_in_place(ptr.cast::<$t>()); } - }); - } - - unsafe { - match STATE.get() { - // 0 == we haven't registered a destructor, so do - // so now. - 0 => { - $crate::thread::local_impl::Key::<$t>::register_dtor( - VAL.get() as *mut $crate::primitive::u8, - destroy, - ); - STATE.set(1); - $crate::option::Option::Some(&*VAL.get()) - } - // 1 == the destructor is registered and the value - // is valid, so return the pointer. - 1 => $crate::option::Option::Some(&*VAL.get()), - // otherwise the destructor has already run, so we - // can't give access. - _ => $crate::option::Option::None, - } - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } - }}, - - // used to generate the `LocalKey` value for `thread_local!` - (@key $t:ty, $init:expr) => { - { - #[inline] - fn __init() -> $t { $init } - - #[inline] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - #[thread_local] - static __KEY: $crate::thread::local_impl::Key<$t> = - $crate::thread::local_impl::Key::<$t>::new(); - - unsafe { - __KEY.get(move || { - if let $crate::option::Option::Some(init) = init { - if let $crate::option::Option::Some(value) = init.take() { - return value; - } - if $crate::cfg!(debug_assertions) { - $crate::unreachable!("missing default value"); - } - } - __init() - }) - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } - } - }, - ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { - $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); - }, -} - -#[derive(Copy, Clone)] -enum DtorState { - Unregistered, - Registered, - RunningOrHasRun, -} - -// This data structure has been carefully constructed so that the fast path -// only contains one branch on x86. That optimization is necessary to avoid -// duplicated tls lookups on OSX. -// -// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 -pub struct Key { - // If `LazyKeyInner::get` returns `None`, that indicates either: - // * The value has never been initialized - // * The value is being recursively initialized - // * The value has already been destroyed or is being destroyed - // To determine which kind of `None`, check `dtor_state`. - // - // This is very optimizer friendly for the fast path - initialized but - // not yet dropped. - inner: LazyKeyInner, - - // Metadata to keep track of the state of the destructor. Remember that - // this variable is thread-local, not global. - dtor_state: Cell, -} - -impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } -} -impl Key { - pub const fn new() -> Key { - Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } - } - - // note that this is just a publicly-callable function only for the - // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in std. - pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - unsafe { - register_dtor(a, dtor); - } - } - - pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { - // SAFETY: See the definitions of `LazyKeyInner::get` and - // `try_initialize` for more information. - // - // The caller must ensure no mutable references are ever active to - // the inner cell or the inner T when this is called. - // The `try_initialize` is dependant on the passed `init` function - // for this. - unsafe { - match self.inner.get() { - Some(val) => Some(val), - None => self.try_initialize(init), - } - } - } - - // `try_initialize` is only called once per fast thread local variable, - // except in corner cases where thread_local dtors reference other - // thread_local's, or it is being recursively initialized. - // - // Macos: Inlining this function can cause two `tlv_get_addr` calls to - // be performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] - unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { - // SAFETY: See comment above (this function doc). - if !mem::needs_drop::() || unsafe { self.try_register_dtor() } { - // SAFETY: See comment above (this function doc). - Some(unsafe { self.inner.initialize(init) }) - } else { - None - } - } - - // `try_register_dtor` is only called once per fast thread local - // variable, except in corner cases where thread_local dtors reference - // other thread_local's, or it is being recursively initialized. - unsafe fn try_register_dtor(&self) -> bool { - match self.dtor_state.get() { - DtorState::Unregistered => { - // SAFETY: dtor registration happens before initialization. - // Passing `self` as a pointer while using `destroy_value` - // is safe because the function will build a pointer to a - // Key, which is the type of self and so find the correct - // size. - unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::) }; - self.dtor_state.set(DtorState::Registered); - true - } - DtorState::Registered => { - // recursively initialized - true - } - DtorState::RunningOrHasRun => false, - } - } -} - -unsafe extern "C" fn destroy_value(ptr: *mut u8) { - let ptr = ptr as *mut Key; - - // SAFETY: - // - // The pointer `ptr` has been built just above and comes from - // `try_register_dtor` where it is originally a Key coming from `self`, - // making it non-NUL and of the correct type. - // - // Right before we run the user destructor be sure to set the - // `Option` to `None`, and `dtor_state` to `RunningOrHasRun`. This - // causes future calls to `get` to run `try_initialize_drop` again, - // which will now fail, and return `None`. - // - // Wrap the call in a catch to ensure unwinding is caught in the event - // a panic takes place in a destructor. - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { - let Key { inner, dtor_state } = &*ptr; - let value = inner.take(); - dtor_state.set(DtorState::RunningOrHasRun); - drop(value); - })) { - rtabort!("thread local panicked on drop"); - } -} diff --git a/library/std/src/sys/thread_local/fast_local/eager.rs b/library/std/src/sys/thread_local/fast_local/eager.rs new file mode 100644 index 0000000000000..c2bc580530ba4 --- /dev/null +++ b/library/std/src/sys/thread_local/fast_local/eager.rs @@ -0,0 +1,82 @@ +use crate::cell::{Cell, UnsafeCell}; +use crate::ptr::{self, drop_in_place}; +use crate::sys::thread_local::abort_on_dtor_unwind; +use crate::sys::thread_local_dtor::register_dtor; + +#[derive(Clone, Copy)] +enum State { + Initial, + Alive, + Destroyed, +} + +#[allow(missing_debug_implementations)] +pub struct Storage { + state: Cell, + val: UnsafeCell, +} + +impl Storage { + pub const fn new(val: T) -> Storage { + Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) } + } + + /// Get a reference to the TLS value. If the TLS variable has been destroyed, + /// `None` is returned. + /// + /// # Safety + /// * The `self` reference must remain valid until the TLS destructor has been + /// run. + /// * The returned reference may only be used until thread destruction occurs + /// and may not be used after reentrant initialization has occurred. + /// + // FIXME(#110897): return NonNull instead of lying about the lifetime. + #[inline] + pub unsafe fn get(&self) -> Option<&'static T> { + match self.state.get() { + // SAFETY: as the state is not `Destroyed`, the value cannot have + // been destroyed yet. The reference fulfills the terms outlined + // above. + State::Alive => unsafe { Some(&*self.val.get()) }, + State::Destroyed => None, + State::Initial => unsafe { self.initialize() }, + } + } + + #[cold] + unsafe fn initialize(&self) -> Option<&'static T> { + // Register the destructor + + // SAFETY: + // * the destructor will be called at thread destruction. + // * the caller guarantees that `self` will be valid until that time. + unsafe { + register_dtor(ptr::from_ref(self).cast_mut().cast(), destroy::); + } + self.state.set(State::Alive); + // SAFETY: as the state is not `Destroyed`, the value cannot have + // been destroyed yet. The reference fulfills the terms outlined + // above. + unsafe { Some(&*self.val.get()) } + } +} + +/// Transition an `Alive` TLS variable into the `Destroyed` state, dropping its +/// value. +/// +/// # Safety +/// * Must only be called at thread destruction. +/// * `ptr` must point to an instance of `Storage` with `Alive` state and be +/// valid for accessing that instance. +unsafe extern "C" fn destroy(ptr: *mut u8) { + // Print a nice abort message if a panic occurs. + abort_on_dtor_unwind(|| { + let storage = unsafe { &*(ptr as *const Storage) }; + // Update the state before running the destructor as it may attempt to + // access the variable. + storage.state.set(State::Destroyed); + unsafe { + drop_in_place(storage.val.get()); + } + }) +} diff --git a/library/std/src/sys/thread_local/fast_local/lazy.rs b/library/std/src/sys/thread_local/fast_local/lazy.rs new file mode 100644 index 0000000000000..14371768d30ce --- /dev/null +++ b/library/std/src/sys/thread_local/fast_local/lazy.rs @@ -0,0 +1,122 @@ +use crate::cell::UnsafeCell; +use crate::hint::unreachable_unchecked; +use crate::mem::forget; +use crate::ptr; +use crate::sys::thread_local::abort_on_dtor_unwind; +use crate::sys::thread_local_dtor::register_dtor; + +pub unsafe trait DestroyedState: Sized { + fn register_dtor(s: &Storage); +} + +unsafe impl DestroyedState for ! { + fn register_dtor(_: &Storage) {} +} + +unsafe impl DestroyedState for () { + fn register_dtor(s: &Storage) { + unsafe { + register_dtor(ptr::from_ref(s).cast_mut().cast(), destroy::); + } + } +} + +enum State { + Initial, + Alive(T), + Destroyed(D), +} + +#[allow(missing_debug_implementations)] +pub struct Storage { + state: UnsafeCell>, +} + +impl Storage +where + D: DestroyedState, +{ + pub const fn new() -> Storage { + Storage { state: UnsafeCell::new(State::Initial) } + } + + /// Get a reference to the TLS value, potentially initializing it with the + /// provided parameters. If the TLS variable has been destroyed, `None` is + /// returned. + /// + /// # Safety + /// * The `self` reference must remain valid until the TLS destructor is run, + /// at which point the returned reference is invalidated. + /// * The returned reference may only be used until thread destruction occurs + /// and may not be used after reentrant initialization has occurred. + /// + // FIXME(#110897): return NonNull instead of lying about the lifetime. + #[inline] + pub unsafe fn get_or_init( + &self, + i: Option<&mut Option>, + f: impl FnOnce() -> T, + ) -> Option<&'static T> { + // SAFETY: + // No mutable reference to the inner value exists outside the calls to + // `replace`. The lifetime of the returned reference fulfills the terms + // outlined above. + let state = unsafe { &*self.state.get() }; + match state { + State::Alive(v) => Some(v), + State::Destroyed(_) => None, + State::Initial => unsafe { self.initialize(i, f) }, + } + } + + #[cold] + unsafe fn initialize( + &self, + i: Option<&mut Option>, + f: impl FnOnce() -> T, + ) -> Option<&'static T> { + // Perform initialization + + let v = i.and_then(Option::take).unwrap_or_else(f); + + // SAFETY: + // If references to the inner value exist, they were created in `f` + // and are invalidated here. The caller promises to never use them + // after this. + let old = unsafe { self.state.get().replace(State::Alive(v)) }; + match old { + // If the variable is not being recursively initialized, register + // the destructor. This might be a noop if the value does not need + // destruction. + State::Initial => D::register_dtor(self), + // Else, drop the old value. This might be changed to a panic. + val => drop(val), + } + + // SAFETY: + // Initialization was completed and the state was set to `Alive`, so the + // reference fulfills the terms outlined above. + unsafe { + let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() }; + Some(v) + } + } +} + +/// Transition an `Alive` TLS variable into the `Destroyed` state, dropping its +/// value. +/// +/// # Safety +/// * Must only be called at thread destruction. +/// * `ptr` must point to an instance of `Storage` and be valid for +/// accessing that instance. +unsafe extern "C" fn destroy(ptr: *mut u8) { + // Print a nice abort message if a panic occurs. + abort_on_dtor_unwind(|| { + let storage = unsafe { &*(ptr as *const Storage) }; + // Update the state before running the destructor as it may attempt to + // access the variable. + let val = unsafe { storage.state.get().replace(State::Destroyed(())) }; + drop(val); + }) +} diff --git a/library/std/src/sys/thread_local/fast_local/mod.rs b/library/std/src/sys/thread_local/fast_local/mod.rs new file mode 100644 index 0000000000000..25379071cb7a6 --- /dev/null +++ b/library/std/src/sys/thread_local/fast_local/mod.rs @@ -0,0 +1,122 @@ +//! Thread local support for platforms with native TLS. +//! +//! To achieve the best performance, we choose from four different types for +//! the TLS variable, depending from the method of initialization used (`const` +//! or lazy) and the drop requirements of the stored type: +//! +//! | | `Drop` | `!Drop` | +//! |--------:|:--------------------:|:-------------------:| +//! | `const` | `EagerStorage` | `T` | +//! | lazy | `LazyStorage` | `LazyStorage` | +//! +//! For `const` initialization and `!Drop` types, we simply use `T` directly, +//! but for other situations, we implement a state machine to handle +//! initialization of the variable and its destructor and destruction. +//! Upon accessing the TLS variable, the current state is compared: +//! +//! 1. If the state is `Initial`, initialize the storage, transition the state +//! to `Alive` and (if applicable) register the destructor, and return a +//! reference to the value. +//! 2. If the state is `Alive`, initialization was previously completed, so +//! return a reference to the value. +//! 3. If the state is `Destroyed`, the destructor has been run already, so +//! return [`None`]. +//! +//! The TLS destructor sets the state to `Destroyed` and drops the current value. +//! +//! To simplify the code, we make `LazyStorage` generic over the destroyed state +//! and use the `!` type (never type) as type parameter for `!Drop` types. This +//! eliminates the `Destroyed` state for these values, which can allow more niche +//! optimizations to occur for the `State` enum. For `Drop` types, `()` is used. + +#![deny(unsafe_op_in_unsafe_fn)] + +mod eager; +mod lazy; + +pub use eager::Storage as EagerStorage; +pub use lazy::Storage as LazyStorage; + +#[doc(hidden)] +#[allow_internal_unstable( + thread_local_internals, + cfg_target_thread_local, + thread_local, + never_type +)] +#[allow_internal_unsafe] +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { + // used to generate the `LocalKey` value for const-initialized thread locals + (@key $t:ty, const $init:expr) => {{ + const __INIT: $t = $init; + + #[inline] + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + _init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + use $crate::thread::local_impl::EagerStorage; + use $crate::mem::needs_drop; + use $crate::ptr::addr_of; + + if needs_drop::<$t>() { + #[thread_local] + static VAL: EagerStorage<$t> = EagerStorage::new(__INIT); + unsafe { + VAL.get() + } + } else { + #[thread_local] + static VAL: $t = __INIT; + unsafe { + $crate::option::Option::Some(&*addr_of!(VAL)) + } + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, + + // used to generate the `LocalKey` value for `thread_local!` + (@key $t:ty, $init:expr) => {{ + #[inline] + fn __init() -> $t { + $init + } + + #[inline] + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + use $crate::thread::local_impl::LazyStorage; + use $crate::mem::needs_drop; + + if needs_drop::<$t>() { + #[thread_local] + static VAL: LazyStorage<$t, ()> = LazyStorage::new(); + unsafe { + VAL.get_or_init(init, __init) + } + } else { + #[thread_local] + static VAL: LazyStorage<$t, !> = LazyStorage::new(); + unsafe { + VAL.get_or_init(init, __init) + } + } + } + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, + ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { + $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index 7500c95d8b473..36f6f907e7213 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -10,12 +10,12 @@ cfg_if::cfg_if! { #[doc(hidden)] mod static_local; #[doc(hidden)] - pub use static_local::{Key, thread_local_inner}; + pub use static_local::{EagerStorage, LazyStorage, thread_local_inner}; } else if #[cfg(target_thread_local)] { #[doc(hidden)] mod fast_local; #[doc(hidden)] - pub use fast_local::{Key, thread_local_inner}; + pub use fast_local::{EagerStorage, LazyStorage, thread_local_inner}; } else { #[doc(hidden)] mod os_local; @@ -24,6 +24,9 @@ cfg_if::cfg_if! { } } +// Not used by the fast-local TLS anymore. +// FIXME(#110897): remove this. +#[allow(unused)] mod lazy { use crate::cell::UnsafeCell; use crate::hint; diff --git a/library/std/src/sys/thread_local/static_local.rs b/library/std/src/sys/thread_local/static_local.rs index 162c3fbd97a0e..6beda2e718802 100644 --- a/library/std/src/sys/thread_local/static_local.rs +++ b/library/std/src/sys/thread_local/static_local.rs @@ -1,5 +1,7 @@ -use super::lazy::LazyKeyInner; -use crate::fmt; +//! On some targets like wasm there's no threads, so no need to generate +//! thread locals and we can instead just use plain statics! + +use crate::cell::UnsafeCell; #[doc(hidden)] #[allow_internal_unstable(thread_local_internals)] @@ -9,22 +11,17 @@ use crate::fmt; pub macro thread_local_inner { // used to generate the `LocalKey` value for const-initialized thread locals (@key $t:ty, const $init:expr) => {{ - #[inline] // see comments below + const __INIT: $t = $init; + + #[inline] #[deny(unsafe_op_in_unsafe_fn)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { - const INIT_EXPR: $t = $init; - - // wasm without atomics maps directly to `static mut`, and dtors - // aren't implemented because thread dtors aren't really a thing - // on wasm right now - // - // FIXME(#84224) this should come after the `target_thread_local` - // block. - static mut VAL: $t = INIT_EXPR; - // SAFETY: we only ever create shared references, so there's no mutable aliasing. - unsafe { $crate::option::Option::Some(&*$crate::ptr::addr_of!(VAL)) } + use $crate::thread::local_impl::EagerStorage; + + static VAL: EagerStorage<$t> = EagerStorage { value: __INIT }; + $crate::option::Option::Some(&VAL.value) } unsafe { @@ -33,74 +30,83 @@ pub macro thread_local_inner { }}, // used to generate the `LocalKey` value for `thread_local!` - (@key $t:ty, $init:expr) => { - { - #[inline] - fn __init() -> $t { $init } - #[inline] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - static __KEY: $crate::thread::local_impl::Key<$t> = - $crate::thread::local_impl::Key::new(); - - unsafe { - __KEY.get(move || { - if let $crate::option::Option::Some(init) = init { - if let $crate::option::Option::Some(value) = init.take() { - return value; - } else if $crate::cfg!(debug_assertions) { - $crate::unreachable!("missing default value"); - } - } - __init() - }) - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } + (@key $t:ty, $init:expr) => {{ + #[inline] + fn __init() -> $t { $init } + + #[inline] + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn __getit( + init: $crate::option::Option<&mut $crate::option::Option<$t>>, + ) -> $crate::option::Option<&'static $t> { + use $crate::thread::local_impl::LazyStorage; + + static VAL: LazyStorage<$t> = LazyStorage::new(); + unsafe { $crate::option::Option::Some(VAL.get(init, __init)) } } - }, + + unsafe { + $crate::thread::LocalKey::new(__getit) + } + }}, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); }, } -/// On some targets like wasm there's no threads, so no need to generate -/// thread locals and we can instead just use plain statics! - -pub struct Key { - inner: LazyKeyInner, +#[allow(missing_debug_implementations)] +pub struct EagerStorage { + pub value: T, } -unsafe impl Sync for Key {} +// SAFETY: the target doesn't have threads. +unsafe impl Sync for EagerStorage {} -impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } +#[allow(missing_debug_implementations)] +pub struct LazyStorage { + value: UnsafeCell>, } -impl Key { - pub const fn new() -> Key { - Key { inner: LazyKeyInner::new() } +impl LazyStorage { + pub const fn new() -> LazyStorage { + LazyStorage { value: UnsafeCell::new(None) } } - pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: The caller must ensure no reference is ever handed out to - // the inner cell nor mutable reference to the Option inside said - // cell. This make it safe to hand a reference, though the lifetime - // of 'static is itself unsafe, making the get method unsafe. - let value = unsafe { - match self.inner.get() { - Some(ref value) => value, - None => self.inner.initialize(init), - } - }; - - Some(value) + /// Gets a reference to the contained value, initializing it if necessary. + /// + /// # Safety + /// The returned reference may not be used after reentrant initialization has occurred. + #[inline] + pub unsafe fn get( + &'static self, + i: Option<&mut Option>, + f: impl FnOnce() -> T, + ) -> &'static T { + let value = unsafe { &*self.value.get() }; + match value { + Some(v) => v, + None => self.initialize(i, f), + } + } + + #[cold] + unsafe fn initialize( + &'static self, + i: Option<&mut Option>, + f: impl FnOnce() -> T, + ) -> &'static T { + let value = i.and_then(Option::take).unwrap_or_else(f); + // Destroy the old value, after updating the TLS variable as the + // destructor might reference it. + // FIXME(#110897): maybe panic on recursive initialization. + unsafe { + self.value.get().replace(Some(value)); + } + // SAFETY: we just set this to `Some`. + unsafe { (*self.value.get()).as_ref().unwrap_unchecked() } } } + +// SAFETY: the target doesn't have threads. +unsafe impl Sync for LazyStorage {} diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 78bc9af6c4d5c..22215873933d6 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -205,7 +205,7 @@ cfg_if::cfg_if! { #[doc(hidden)] #[unstable(feature = "thread_local_internals", issue = "none")] pub mod local_impl { - pub use crate::sys::thread_local::{thread_local_inner, Key, abort_on_dtor_unwind}; + pub use crate::sys::thread_local::*; } } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 38de5e3800005..52c94465cd33d 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -92,8 +92,6 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (Some(Mode::Std), "no_global_oom_handling", None), (Some(Mode::Std), "no_rc", None), (Some(Mode::Std), "no_sync", None), - (Some(Mode::Std), "netbsd10", None), - (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])), (Some(Mode::Std), "target_os", Some(&["visionos"])), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b54ec62452476..7aab07c06a33c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1937,7 +1937,7 @@ impl PrimitiveType { let mut primitive_locations = FxHashMap::default(); // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate. // This is a degenerate case that I don't plan to support. - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let e = ExternalCrate { crate_num }; let crate_name = e.name(tcx); debug!(?crate_num, ?crate_name); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index feb03b9a823e8..462b31f159b35 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt( show_coverage, }; - for cnum in tcx.crates(()) { + for cnum in tcx.crates_including_speculative(()) { crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id()); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index a3b88a880f2af..28ddf76a3a695 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -155,7 +155,7 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let e = ExternalCrate { crate_num }; let name = e.name(tcx); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index c92cf9d3e80d3..22daac9efb152 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // External trait impls. { let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls"); - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { for &impl_def_id in tcx.trait_impls_in_crate(cnum) { cx.with_param_env(impl_def_id, |cx| { inline::build_impl(cx, impl_def_id, None, &mut new_items_external); diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index e9b380fdeac66..64753a58a2bff 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -283,7 +283,7 @@ pub(crate) fn run( // Collect CrateIds corresponding to provided target crates // If two different versions of the crate in the dependency tree, then examples will be collected from both. let all_crates = tcx - .crates(()) + .crates_including_speculative(()) .iter() .chain([&LOCAL_CRATE]) .map(|crate_num| (crate_num, tcx.crate_name(*crate_num))) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4c603bda770a9..94d4656377f98 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec, path: &[&str]) -> Vec { fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator + '_ { - tcx.crates(()) + tcx.crates_including_speculative(()) .iter() .copied() .filter(move |&num| tcx.crate_name(num) == name) diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 10726b9842080..29e8809e5bd66 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -282,7 +282,7 @@ fn push_expected_errors( // Add notes for the backtrace for span in primary_spans { - for frame in &span.expansion { + if let Some(frame) = &span.expansion { push_backtrace(expected_errors, frame, file_name); } } @@ -315,7 +315,7 @@ fn push_backtrace( }); } - for previous_expansion in &expansion.span.expansion { + if let Some(previous_expansion) = &expansion.span.expansion { push_backtrace(expected_errors, previous_expansion, file_name); } } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 22a6a297259d9..d3840775da969 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9cdfe285ca724c801dc9f78d22b24ea69b787f26 +78dd504f2fd87c0cfabff7d9174253411caf2f80 diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 3e8703d5cfc89..a288477857878 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -648,7 +648,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { place: &MPlaceTy<'tcx, Provenance>, rhs: &ImmTy<'tcx, Provenance>, op: mir::BinOp, - neg: bool, + not: bool, atomic: AtomicRwOrd, ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); @@ -656,9 +656,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; - // Atomics wrap around on overflow. - let val = this.wrapping_binary_op(op, &old, rhs)?; - let val = if neg { this.wrapping_unary_op(mir::UnOp::Not, &val)? } else { val }; + let val = this.binary_op(op, &old, rhs)?; + let val = if not { this.unary_op(mir::UnOp::Not, &val)? } else { val }; this.allow_data_races_mut(|this| this.write_immediate(*val, place))?; this.validate_atomic_rmw(place, atomic)?; @@ -700,7 +699,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { this.atomic_access_check(place, AtomicAccessType::Rmw)?; let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; - let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; + let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; #[rustfmt::skip] // rustfmt makes this unreadable let new_val = if min { @@ -744,7 +743,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { // Read as immediate for the sake of `binary_op()` let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; // `binary_op` will bail if either of them is not a scalar. - let eq = this.wrapping_binary_op(mir::BinOp::Eq, &old, expect_old)?; + let eq = this.binary_op(mir::BinOp::Eq, &old, expect_old)?; // If the operation would succeed, but is "weak", fail some portion // of the time, based on `success_rate`. let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate; diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 4050ae3c4bf97..bd160380cd524 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -126,7 +126,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option) // the one in the sysroot and the one locally built by `cargo test`.) // FIXME: can we prefer the one from the sysroot? 'crates: for krate in - tcx.crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) + tcx.used_crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) { let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX }; // Go over the modules. @@ -1365,7 +1365,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec { .map(|crates| crates.split(',').map(|krate| krate.to_string()).collect::>()) .unwrap_or_default(); let mut local_crates = Vec::new(); - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let name = tcx.crate_name(crate_num); let name = name.as_str(); if local_crate_names.iter().any(|local_name| local_name == name) { diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index 501dbc1603e67..0daf59c943ced 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -4,8 +4,8 @@ use crate::*; use helpers::check_arg_count; pub enum AtomicOp { - /// The `bool` indicates whether the result of the operation should be negated - /// (must be a boolean-typed operation). + /// The `bool` indicates whether the result of the operation should be negated (`UnOp::Not`, + /// must be a boolean-typed operation). MirOp(mir::BinOp, bool), Max, Min, @@ -213,8 +213,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { this.write_immediate(*old, dest)?; // old value is returned Ok(()) } - AtomicOp::MirOp(op, neg) => { - let old = this.atomic_rmw_op_immediate(&place, &rhs, op, neg, atomic)?; + AtomicOp::MirOp(op, not) => { + let old = this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)?; this.write_immediate(*old, dest)?; // old value is returned Ok(()) } diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index fdf637f2e8f43..973a0c84a882c 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -362,8 +362,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "frem_algebraic" => mir::BinOp::Rem, _ => bug!(), }; - let res = this.wrapping_binary_op(op, &a, &b)?; - // `wrapping_binary_op` already called `generate_nan` if necessary. + let res = this.binary_op(op, &a, &b)?; + // `binary_op` already called `generate_nan` if necessary. this.write_immediate(*res, dest)?; } @@ -408,12 +408,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ), _ => {} } - let res = this.wrapping_binary_op(op, &a, &b)?; + let res = this.binary_op(op, &a, &b)?; if !float_finite(&res)? { throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result"); } // This cannot be a NaN so we also don't have to apply any non-determinism. - // (Also, `wrapping_binary_op` already called `generate_nan` if needed.) + // (Also, `binary_op` already called `generate_nan` if needed.) this.write_immediate(*res, dest)?; } diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index e178187ffa621..67a2d565fa2f6 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -1,3 +1,5 @@ +use either::Either; + use rustc_apfloat::{Float, Round}; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::{mir, ty, ty::FloatTy}; @@ -82,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let val = match which { Op::MirOp(mir_op) => { // This already does NaN adjustments - this.wrapping_unary_op(mir_op, &op)?.to_scalar() + this.unary_op(mir_op, &op)?.to_scalar() } Op::Abs => { // Works for f32 and f64. @@ -217,8 +219,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "mul" => Op::MirOp(BinOp::Mul), "div" => Op::MirOp(BinOp::Div), "rem" => Op::MirOp(BinOp::Rem), - "shl" => Op::MirOp(BinOp::Shl), - "shr" => Op::MirOp(BinOp::Shr), + "shl" => Op::MirOp(BinOp::ShlUnchecked), + "shr" => Op::MirOp(BinOp::ShrUnchecked), "and" => Op::MirOp(BinOp::BitAnd), "or" => Op::MirOp(BinOp::BitOr), "xor" => Op::MirOp(BinOp::BitXor), @@ -243,15 +245,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let val = match which { Op::MirOp(mir_op) => { // This does NaN adjustments. - let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?; - if matches!(mir_op, BinOp::Shl | BinOp::Shr) { - // Shifts have extra UB as SIMD operations that the MIR binop does not have. - // See . - if overflowed { - let r_val = right.to_scalar().to_bits(right.layout.size)?; - throw_ub_format!("overflowing shift by {r_val} in `simd_{intrinsic_name}` in SIMD lane {i}"); + let val = this.binary_op(mir_op, &left, &right).map_err(|err| { + match err.kind() { + InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => { + // This resets the interpreter backtrace, but it's not worth avoiding that. + let shift_amount = match shift_amount { + Either::Left(v) => v.to_string(), + Either::Right(v) => v.to_string(), + }; + err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}").into() + } + _ => err } - } + })?; if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) { // Special handling for boolean-returning operations assert_eq!(val.layout.ty, this.tcx.types.bool); @@ -370,11 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = this.read_immediate(&this.project_index(&op, i)?)?; res = match which { Op::MirOp(mir_op) => { - this.wrapping_binary_op(mir_op, &res, &op)? + this.binary_op(mir_op, &res, &op)? } Op::MirOpBool(mir_op) => { let op = imm_from_bool(simd_element_to_bool(op)?); - this.wrapping_binary_op(mir_op, &res, &op)? + this.binary_op(mir_op, &res, &op)? } Op::MinMax(mmop) => { if matches!(res.layout.ty.kind(), ty::Float(_)) { @@ -385,7 +391,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { MinMax::Min => BinOp::Le, MinMax::Max => BinOp::Ge, }; - if this.wrapping_binary_op(mirop, &res, &op)?.to_scalar().to_bool()? { + if this.binary_op(mirop, &res, &op)?.to_scalar().to_bool()? { res } else { op @@ -414,7 +420,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut res = init; for i in 0..op_len { let op = this.read_immediate(&this.project_index(&op, i)?)?; - res = this.wrapping_binary_op(mir_op, &res, &op)?; + res = this.binary_op(mir_op, &res, &op)?; } this.write_immediate(*res, dest)?; } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index cbf02d701bcf5..0c6a2560b1332 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1025,7 +1025,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { bin_op: mir::BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { ecx.binary_ptr_op(bin_op, left, right) } diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index d99be39177bcf..7a008266dbc89 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -14,7 +14,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { bin_op: mir::BinOp, left: &ImmTy<'tcx, Provenance>, right: &ImmTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> { + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { use rustc_middle::mir::BinOp::*; let this = self.eval_context_ref(); @@ -45,7 +45,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ge => left >= right, _ => bug!(), }; - (ImmTy::from_bool(res, *this.tcx), false) + ImmTy::from_bool(res, *this.tcx) } // Some more operations are possible with atomics. @@ -60,16 +60,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { right.to_scalar().to_target_usize(this)?, this.machine.layouts.usize, ); - let (result, overflowing) = this.overflowing_binary_op(bin_op, &left, &right)?; + let result = this.binary_op(bin_op, &left, &right)?; // Construct a new pointer with the provenance of `ptr` (the LHS). let result_ptr = Pointer::new( ptr.provenance, Size::from_bytes(result.to_scalar().to_target_usize(this)?), ); - ( - ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, this), left.layout), - overflowing, - ) + + ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, this), left.layout) } _ => span_bug!(this.cur_span(), "Invalid operator on pointers: {:?}", bin_op), diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 48b7222917b51..04ad979cf5d57 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -50,13 +50,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let a = this.read_immediate(a)?; let b = this.read_immediate(b)?; - let (sum, overflow1) = this.overflowing_binary_op(mir::BinOp::Add, &a, &b)?; - let (sum, overflow2) = this.overflowing_binary_op( - mir::BinOp::Add, - &sum, - &ImmTy::from_uint(c_in, a.layout), - )?; - let c_out = overflow1 | overflow2; + let (sum, overflow1) = + this.binary_op(mir::BinOp::AddWithOverflow, &a, &b)?.to_pair(this); + let (sum, overflow2) = this + .binary_op( + mir::BinOp::AddWithOverflow, + &sum, + &ImmTy::from_uint(c_in, a.layout), + )? + .to_pair(this); + let c_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?; this.write_scalar(Scalar::from_u8(c_out.into()), &this.project_field(dest, 0)?)?; this.write_immediate(*sum, &this.project_field(dest, 1)?)?; @@ -76,13 +79,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let a = this.read_immediate(a)?; let b = this.read_immediate(b)?; - let (sub, overflow1) = this.overflowing_binary_op(mir::BinOp::Sub, &a, &b)?; - let (sub, overflow2) = this.overflowing_binary_op( - mir::BinOp::Sub, - &sub, - &ImmTy::from_uint(b_in, a.layout), - )?; - let b_out = overflow1 | overflow2; + let (sub, overflow1) = + this.binary_op(mir::BinOp::SubWithOverflow, &a, &b)?.to_pair(this); + let (sub, overflow2) = this + .binary_op( + mir::BinOp::SubWithOverflow, + &sub, + &ImmTy::from_uint(b_in, a.layout), + )? + .to_pair(this); + let b_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?; this.write_scalar(Scalar::from_u8(b_out.into()), &this.project_field(dest, 0)?)?; this.write_immediate(*sub, &this.project_field(dest, 1)?)?; @@ -245,7 +251,7 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>( ) -> InterpResult<'tcx, Scalar> { match which { FloatBinOp::Arith(which) => { - let res = this.wrapping_binary_op(which, left, right)?; + let res = this.binary_op(which, left, right)?; Ok(res.to_scalar()) } FloatBinOp::Cmp { gt, lt, eq, unord } => { @@ -744,12 +750,9 @@ fn int_abs<'tcx>( let op = this.read_immediate(&this.project_index(&op, i)?)?; let dest = this.project_index(&dest, i)?; - let lt_zero = this.wrapping_binary_op(mir::BinOp::Lt, &op, &zero)?; - let res = if lt_zero.to_scalar().to_bool()? { - this.wrapping_unary_op(mir::UnOp::Neg, &op)? - } else { - op - }; + let lt_zero = this.binary_op(mir::BinOp::Lt, &op, &zero)?; + let res = + if lt_zero.to_scalar().to_bool()? { this.unary_op(mir::UnOp::Neg, &op)? } else { op }; this.write_immediate(*res, &dest)?; } @@ -832,7 +835,7 @@ fn horizontal_bin_op<'tcx>( let res = if saturating { Immediate::from(this.saturating_arith(which, &lhs, &rhs)?) } else { - *this.wrapping_binary_op(which, &lhs, &rhs)? + *this.binary_op(which, &lhs, &rhs)? }; this.write_immediate(res, &this.project_index(&dest, j)?)?; @@ -884,8 +887,8 @@ fn conditional_dot_product<'tcx>( let left = this.read_immediate(&this.project_index(&left, j)?)?; let right = this.read_immediate(&this.project_index(&right, j)?)?; - let mul = this.wrapping_binary_op(mir::BinOp::Mul, &left, &right)?; - sum = this.wrapping_binary_op(mir::BinOp::Add, &sum, &mul)?; + let mul = this.binary_op(mir::BinOp::Mul, &left, &right)?; + sum = this.binary_op(mir::BinOp::Add, &sum, &mul)?; } } @@ -1276,11 +1279,8 @@ fn psign<'tcx>( let left = this.read_immediate(&this.project_index(&left, i)?)?; let right = this.read_scalar(&this.project_index(&right, i)?)?.to_int(dest.layout.size)?; - let res = this.wrapping_binary_op( - mir::BinOp::Mul, - &left, - &ImmTy::from_int(right.signum(), dest.layout), - )?; + let res = + this.binary_op(mir::BinOp::Mul, &left, &ImmTy::from_int(right.signum(), dest.layout))?; this.write_immediate(*res, &dest)?; } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs index 8a49c8403ae37..12aa7c10af4e4 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs @@ -10,6 +10,6 @@ fn main() { unsafe { let x = i32x2(1, 1); let y = i32x2(100, 0); - simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in SIMD lane 0 + simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in lane 0 } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr index 3a4ec008b449a..475067db801e2 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflowing shift by 100 in `simd_shl` in SIMD lane 0 +error: Undefined Behavior: overflowing shift by 100 in `simd_shl` in lane 0 --> $DIR/simd-shl-too-far.rs:LL:CC | LL | simd_shl(x, y); - | ^^^^^^^^^^^^^^ overflowing shift by 100 in `simd_shl` in SIMD lane 0 + | ^^^^^^^^^^^^^^ overflowing shift by 100 in `simd_shl` in lane 0 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs index 433998cbde665..ada7cf408c4ed 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs @@ -10,6 +10,6 @@ fn main() { unsafe { let x = i32x2(1, 1); let y = i32x2(20, 40); - simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in SIMD lane 1 + simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in lane 1 } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr index 07636b8c0bbd3..0d6307837deb5 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflowing shift by 40 in `simd_shr` in SIMD lane 1 +error: Undefined Behavior: overflowing shift by 40 in `simd_shr` in lane 1 --> $DIR/simd-shr-too-far.rs:LL:CC | LL | simd_shr(x, y); - | ^^^^^^^^^^^^^^ overflowing shift by 40 in `simd_shr` in SIMD lane 1 + | ^^^^^^^^^^^^^^ overflowing shift by 40 in `simd_shr` in lane 1 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs index 3f8b4e55151ec..0ed758da2a3c7 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs @@ -1,4 +1,4 @@ fn main() { // MAX overflow - let _val = unsafe { 40000u16.unchecked_add(30000) }; //~ ERROR: overflow executing `unchecked_add` + let _val = unsafe { 40000u16.unchecked_add(30000) }; //~ ERROR: arithmetic overflow in `unchecked_add` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr index 922de4226fa80..eae9ec7a44dcd 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_add` +error: Undefined Behavior: arithmetic overflow in `unchecked_add` --> $DIR/unchecked_add1.rs:LL:CC | LL | let _val = unsafe { 40000u16.unchecked_add(30000) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs index 3283dbf8e7ef3..3b495203eb41f 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs @@ -1,4 +1,4 @@ fn main() { // MIN overflow - let _val = unsafe { (-30000i16).unchecked_add(-8000) }; //~ ERROR: overflow executing `unchecked_add` + let _val = unsafe { (-30000i16).unchecked_add(-8000) }; //~ ERROR: arithmetic overflow in `unchecked_add` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr index 05456eaf19509..6a0dcfcd227e7 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_add` +error: Undefined Behavior: arithmetic overflow in `unchecked_add` --> $DIR/unchecked_add2.rs:LL:CC | LL | let _val = unsafe { (-30000i16).unchecked_add(-8000) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs index 2feed7759ec1c..3dc83a2dcef28 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs @@ -1,4 +1,4 @@ fn main() { // MAX overflow - let _val = unsafe { 300u16.unchecked_mul(250u16) }; //~ ERROR: overflow executing `unchecked_mul` + let _val = unsafe { 300u16.unchecked_mul(250u16) }; //~ ERROR: arithmetic overflow in `unchecked_mul` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr index 533beaa65ff77..e37d9827c8cf6 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_mul` +error: Undefined Behavior: arithmetic overflow in `unchecked_mul` --> $DIR/unchecked_mul1.rs:LL:CC | LL | let _val = unsafe { 300u16.unchecked_mul(250u16) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs index 42cd509404a55..49cd293737c71 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs @@ -1,4 +1,4 @@ fn main() { // MIN overflow - let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; //~ ERROR: overflow executing `unchecked_mul` + let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; //~ ERROR: arithmetic overflow in `unchecked_mul` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr index 4c6bae6f0bf68..949077ce61d8c 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_mul` +error: Undefined Behavior: arithmetic overflow in `unchecked_mul` --> $DIR/unchecked_mul2.rs:LL:CC | LL | let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs index e5178bf4effaa..f24c97420948c 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs @@ -1,4 +1,4 @@ fn main() { // MIN overflow - let _val = unsafe { 14u32.unchecked_sub(22) }; //~ ERROR: overflow executing `unchecked_sub` + let _val = unsafe { 14u32.unchecked_sub(22) }; //~ ERROR: arithmetic overflow in `unchecked_sub` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr index 72187e20e23c3..39bfd8a238404 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_sub` +error: Undefined Behavior: arithmetic overflow in `unchecked_sub` --> $DIR/unchecked_sub1.rs:LL:CC | LL | let _val = unsafe { 14u32.unchecked_sub(22) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub` + | ^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs index ac9fd1e5d0622..74b08b1dfb4e0 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs @@ -1,4 +1,4 @@ fn main() { // MAX overflow - let _val = unsafe { 30000i16.unchecked_sub(-7000) }; //~ ERROR: overflow executing `unchecked_sub` + let _val = unsafe { 30000i16.unchecked_sub(-7000) }; //~ ERROR: arithmetic overflow in `unchecked_sub` } diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr index ec28384f6336f..604eba99e0147 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: overflow executing `unchecked_sub` +error: Undefined Behavior: arithmetic overflow in `unchecked_sub` --> $DIR/unchecked_sub2.rs:LL:CC | LL | let _val = unsafe { 30000i16.unchecked_sub(-7000) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub` | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index a67f5c8a9ee43..799c36b104999 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -45,6 +45,14 @@ impl Cc { self } + /// Adds directories to the list that the linker searches for libraries. + /// Equivalent to `-L`. + pub fn library_search_path>(&mut self, path: P) -> &mut Self { + self.cmd.arg("-L"); + self.cmd.arg(path.as_ref()); + self + } + /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable /// is under `$TMPDIR`. pub fn out_exe(&mut self, name: &str) -> &mut Self { diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index f581204d5f1cb..1c83b630861cd 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -156,13 +156,20 @@ impl Rustc { self } - /// Add a directory to the library search path. Equivalent to `-L`` in rustc. + /// Add a directory to the library search path. Equivalent to `-L` in rustc. pub fn library_search_path>(&mut self, path: P) -> &mut Self { self.cmd.arg("-L"); self.cmd.arg(path.as_ref()); self } + /// Override the system root. Equivalent to `--sysroot` in rustc. + pub fn sysroot>(&mut self, path: P) -> &mut Self { + self.cmd.arg("--sysroot"); + self.cmd.arg(path.as_ref()); + self + } + /// Specify the edition year. pub fn edition(&mut self, edition: &str) -> &mut Self { self.cmd.arg("--edition"); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 9233dd8c89f6c..ad900ce038618 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -25,7 +25,6 @@ run-make/compiler-rt-works-on-mingw/Makefile run-make/compressed-debuginfo/Makefile run-make/const-prop-lint/Makefile run-make/const_fn_mir/Makefile -run-make/core-no-oom-handling/Makefile run-make/crate-data-smoke/Makefile run-make/crate-hash-rustc-version/Makefile run-make/crate-name-priority/Makefile @@ -98,24 +97,19 @@ run-make/issue-15460/Makefile run-make/issue-18943/Makefile run-make/issue-20626/Makefile run-make/issue-22131/Makefile -run-make/issue-24445/Makefile run-make/issue-25581/Makefile run-make/issue-26006/Makefile run-make/issue-26092/Makefile run-make/issue-28595/Makefile -run-make/issue-30063/Makefile run-make/issue-33329/Makefile run-make/issue-35164/Makefile run-make/issue-36710/Makefile run-make/issue-37839/Makefile run-make/issue-37893/Makefile -run-make/issue-38237/Makefile run-make/issue-40535/Makefile -run-make/issue-46239/Makefile run-make/issue-47384/Makefile run-make/issue-47551/Makefile run-make/issue-51671/Makefile -run-make/issue-53964/Makefile run-make/issue-64153/Makefile run-make/issue-68794-textrel-on-minimal-lib/Makefile run-make/issue-69368/Makefile @@ -233,7 +227,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile run-make/rustdoc-io-error/Makefile -run-make/rustdoc-scrape-examples-macros/Makefile run-make/rustdoc-verify-output-files/Makefile run-make/rustdoc-with-output-option/Makefile run-make/sanitizer-cdylib-link/Makefile diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 6b8106bbc214a..881b4f84173ca 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3988,8 +3988,6 @@ ui/test-attrs/issue-52557.rs ui/test-attrs/issue-53675-a-test-called-panic.rs ui/threads-sendsync/issue-24313.rs ui/threads-sendsync/issue-29488.rs -ui/threads-sendsync/issue-43733-2.rs -ui/threads-sendsync/issue-43733.rs ui/threads-sendsync/issue-4446.rs ui/threads-sendsync/issue-4448.rs ui/threads-sendsync/issue-8827.rs diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 9cabab582d0d8..64cc227762055 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -243,7 +243,7 @@ pub fn is_in(full_path: &Path, parent_folder_to_find: &str, folder_to_find: &str if parent.file_name().map_or_else( || false, |f| { - f.to_string_lossy() == folder_to_find + f == folder_to_find && parent .parent() .and_then(|f| f.file_name()) diff --git a/tests/codegen/noalias-freeze.rs b/tests/codegen/noalias-freeze.rs new file mode 100644 index 0000000000000..8086f3afbbc87 --- /dev/null +++ b/tests/codegen/noalias-freeze.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Copt-level=1 + +// References returned by a Frozen pointer type +// could be marked as "noalias", which caused miscompilation errors. +// This test runs the most minimal possible code that can reproduce this bug, +// and checks that noalias does not appear. +// See https://github.com/rust-lang/rust/issues/46239 + +#![crate_type = "lib"] + +fn project(x: &(T,)) -> &T { &x.0 } + +fn dummy() {} + +// CHECK-LABEL: @foo( +// CHECK-NOT: noalias +#[no_mangle] +pub fn foo() { + let f = (dummy as fn(),); + (*project(&f))(); +} diff --git a/tests/crashes/124348.rs b/tests/crashes/124348.rs deleted file mode 100644 index 554f383026cbd..0000000000000 --- a/tests/crashes/124348.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #124348 -enum Eek { - TheConst, - UnusedByTheConst(Sum), -} - -const EEK_ZERO: &[Eek] = &[]; diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs index fec3c6532940e..4bca5d1f1efbe 100644 --- a/tests/run-make/alloc-no-oom-handling/rmake.rs +++ b/tests/run-make/alloc-no-oom-handling/rmake.rs @@ -1,4 +1,4 @@ -// This test checks that alloc can still compile correctly +// This test checks that alloc can still compile successfully // when the unstable no_global_oom_handling feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs index c5744a3f5eef5..8ff73324b0832 100644 --- a/tests/run-make/alloc-no-rc/rmake.rs +++ b/tests/run-make/alloc-no-rc/rmake.rs @@ -1,4 +1,4 @@ -// This test checks that alloc can still compile correctly +// This test checks that alloc can still compile successfully // when the unstable no_rc feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs index 6410eca80abff..3a3ceed686792 100644 --- a/tests/run-make/alloc-no-sync/rmake.rs +++ b/tests/run-make/alloc-no-sync/rmake.rs @@ -1,4 +1,4 @@ -// This test checks that alloc can still compile correctly +// This test checks that alloc can still compile successfully // when the unstable no_sync feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 diff --git a/tests/run-make/core-no-oom-handling/Makefile b/tests/run-make/core-no-oom-handling/Makefile deleted file mode 100644 index 28c5261ff854d..0000000000000 --- a/tests/run-make/core-no-oom-handling/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include ../tools.mk - -FAKEROOT=$(TMPDIR)/fakeroot - -all: - $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../library/core/src/lib.rs --sysroot=$(FAKEROOT) --cfg no_global_oom_handling diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs new file mode 100644 index 0000000000000..75767421cd1fa --- /dev/null +++ b/tests/run-make/core-no-oom-handling/rmake.rs @@ -0,0 +1,16 @@ +// This test checks that the core library can still compile successfully +// when the no_global_oom_handling feature is turned on. +// See https://github.com/rust-lang/rust/pull/110649 + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc() + .edition("2021") + .arg("-Dwarnings") + .crate_type("rlib") + .input("../../../library/core/src/lib.rs") + .sysroot(tmp_dir().join("fakeroot")) + .cfg("no_global_oom_handling") + .run(); +} diff --git a/tests/run-make/issue-38237/bar.rs b/tests/run-make/deref-impl-rustdoc-ice/bar.rs similarity index 100% rename from tests/run-make/issue-38237/bar.rs rename to tests/run-make/deref-impl-rustdoc-ice/bar.rs diff --git a/tests/run-make/issue-38237/baz.rs b/tests/run-make/deref-impl-rustdoc-ice/baz.rs similarity index 100% rename from tests/run-make/issue-38237/baz.rs rename to tests/run-make/deref-impl-rustdoc-ice/baz.rs diff --git a/tests/run-make/issue-38237/foo.rs b/tests/run-make/deref-impl-rustdoc-ice/foo.rs similarity index 100% rename from tests/run-make/issue-38237/foo.rs rename to tests/run-make/deref-impl-rustdoc-ice/foo.rs diff --git a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs new file mode 100644 index 0000000000000..c2156de03a974 --- /dev/null +++ b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs @@ -0,0 +1,16 @@ +// A very specific set of circumstances (mainly, implementing Deref, and +// having a procedural macro and a Debug derivation in external crates) caused +// an internal compiler error (ICE) when trying to use rustdoc. This test +// reproduces the exact circumstances which caused the bug and checks +// that it does not happen again. +// See https://github.com/rust-lang/rust/issues/38237 + +//@ ignore-cross-compile + +use run_make_support::{rustc, rustdoc, tmp_dir}; + +fn main() { + rustc().input("foo.rs").run(); + rustc().input("bar.rs").run(); + rustdoc().input("baz.rs").library_search_path(tmp_dir()).output(tmp_dir()).run(); +} diff --git a/tests/run-make/issue-53964/app.rs b/tests/run-make/external-crate-panic-handle-no-lint/app.rs similarity index 100% rename from tests/run-make/issue-53964/app.rs rename to tests/run-make/external-crate-panic-handle-no-lint/app.rs diff --git a/tests/run-make/issue-53964/panic.rs b/tests/run-make/external-crate-panic-handle-no-lint/panic.rs similarity index 100% rename from tests/run-make/issue-53964/panic.rs rename to tests/run-make/external-crate-panic-handle-no-lint/panic.rs diff --git a/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs new file mode 100644 index 0000000000000..de4023282ef6e --- /dev/null +++ b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs @@ -0,0 +1,12 @@ +// Defining a crate that provides panic handling as an external crate +// could uselessly trigger the "unused external crate" lint. In this test, +// if the lint is triggered, it will trip #![deny(unused_extern_crates)], +// and cause the test to fail. +// See https://github.com/rust-lang/rust/issues/53964 + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().input("panic.rs").run(); + rustc().input("app.rs").panic("abort").emit("obj").library_search_path(tmp_dir()).run(); +} diff --git a/tests/run-make/issue-24445/Makefile b/tests/run-make/issue-24445/Makefile deleted file mode 100644 index a13910aa73ed0..0000000000000 --- a/tests/run-make/issue-24445/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# only-linux - -all: - $(RUSTC) foo.rs - $(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -o $(TMPDIR)/foo - $(call RUN,foo) - $(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -pie -fPIC -o $(TMPDIR)/foo - $(call RUN,foo) diff --git a/tests/run-make/issue-30063/Makefile b/tests/run-make/issue-30063/Makefile deleted file mode 100644 index 8a69ca79f5150..0000000000000 --- a/tests/run-make/issue-30063/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - rm -f $(TMPDIR)/foo-output - $(RUSTC) -C codegen-units=4 -o $(TMPDIR)/foo-output foo.rs - rm $(TMPDIR)/foo-output - - rm -f $(TMPDIR)/asm-output - $(RUSTC) -C codegen-units=4 --emit=asm -o $(TMPDIR)/asm-output foo.rs - rm $(TMPDIR)/asm-output - - rm -f $(TMPDIR)/bc-output - $(RUSTC) -C codegen-units=4 --emit=llvm-bc -o $(TMPDIR)/bc-output foo.rs - rm $(TMPDIR)/bc-output - - rm -f $(TMPDIR)/ir-output - $(RUSTC) -C codegen-units=4 --emit=llvm-ir -o $(TMPDIR)/ir-output foo.rs - rm $(TMPDIR)/ir-output - - rm -f $(TMPDIR)/link-output - $(RUSTC) -C codegen-units=4 --emit=link -o $(TMPDIR)/link-output foo.rs - rm $(TMPDIR)/link-output - - rm -f $(TMPDIR)/obj-output - $(RUSTC) -C codegen-units=4 --emit=obj -o $(TMPDIR)/obj-output foo.rs - rm $(TMPDIR)/obj-output - - rm -f $(TMPDIR)/dep-output - $(RUSTC) -C codegen-units=4 --emit=dep-info -o $(TMPDIR)/dep-output foo.rs - rm $(TMPDIR)/dep-output - -# # (This case doesn't work yet, and may be fundamentally wrong-headed anyway.) -# rm -f $(TMPDIR)/multi-output -# $(RUSTC) -C codegen-units=4 --emit=asm,obj -o $(TMPDIR)/multi-output foo.rs -# rm $(TMPDIR)/multi-output diff --git a/tests/run-make/issue-38237/Makefile b/tests/run-make/issue-38237/Makefile deleted file mode 100644 index 80dddc5bd1331..0000000000000 --- a/tests/run-make/issue-38237/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo.rs; $(RUSTC) bar.rs - $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR) diff --git a/tests/run-make/issue-46239/Makefile b/tests/run-make/issue-46239/Makefile deleted file mode 100644 index 0006ced25156a..0000000000000 --- a/tests/run-make/issue-46239/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) main.rs -C opt-level=1 - $(call RUN,main) diff --git a/tests/run-make/issue-46239/main.rs b/tests/run-make/issue-46239/main.rs deleted file mode 100644 index b7df5cf4d8128..0000000000000 --- a/tests/run-make/issue-46239/main.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn project(x: &(T,)) -> &T { &x.0 } - -fn dummy() {} - -fn main() { - let f = (dummy as fn(),); - (*project(&f))(); -} diff --git a/tests/run-make/issue-53964/Makefile b/tests/run-make/issue-53964/Makefile deleted file mode 100644 index 6bd83021374d9..0000000000000 --- a/tests/run-make/issue-53964/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) panic.rs - $(RUSTC) -C panic=abort --emit=obj app.rs -L $(TMPDIR) diff --git a/tests/run-make/issue-24445/foo.c b/tests/run-make/non-pie-thread-local/foo.c similarity index 100% rename from tests/run-make/issue-24445/foo.c rename to tests/run-make/non-pie-thread-local/foo.c diff --git a/tests/run-make/issue-24445/foo.rs b/tests/run-make/non-pie-thread-local/foo.rs similarity index 100% rename from tests/run-make/issue-24445/foo.rs rename to tests/run-make/non-pie-thread-local/foo.rs diff --git a/tests/run-make/non-pie-thread-local/rmake.rs b/tests/run-make/non-pie-thread-local/rmake.rs new file mode 100644 index 0000000000000..1ef447e786019 --- /dev/null +++ b/tests/run-make/non-pie-thread-local/rmake.rs @@ -0,0 +1,34 @@ +// It was once required to use a position-independent executable (PIE) +// in order to use the thread_local! macro, or some symbols would contain +// a NULL address. This was fixed, and this test checks a non-PIE, then a PIE +// build to see if this bug makes a resurgence. +// See https://github.com/rust-lang/rust/pull/24448 + +//@ ignore-cross-compile +//@ only-linux + +use run_make_support::{cc, run, rustc, tmp_dir}; + +fn main() { + rustc().input("foo.rs").run(); + cc().input("foo.c") + .arg("-lfoo") + .library_search_path(tmp_dir()) + .arg("-Wl,--gc-sections") + .arg("-lpthread") + .arg("-ldl") + .out_exe("foo") + .run(); + run("foo"); + cc().input("foo.c") + .arg("-lfoo") + .library_search_path(tmp_dir()) + .arg("-Wl,--gc-sections") + .arg("-lpthread") + .arg("-ldl") + .arg("-pie") + .arg("-fPIC") + .out_exe("foo") + .run(); + run("foo"); +} diff --git a/tests/run-make/issue-30063/foo.rs b/tests/run-make/reset-codegen-1/foo.rs similarity index 100% rename from tests/run-make/issue-30063/foo.rs rename to tests/run-make/reset-codegen-1/foo.rs diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs new file mode 100644 index 0000000000000..4b91ba7df90bd --- /dev/null +++ b/tests/run-make/reset-codegen-1/rmake.rs @@ -0,0 +1,38 @@ +// When rustc received 4 codegen-units, an output path and an emit flag all simultaneously, +// this could cause an annoying recompilation issue, uselessly lengthening the build process. +// A fix was delivered, which resets codegen-units to 1 when necessary, +// but as it directly affected the way codegen-units are manipulated, +// this test was created to check that this fix did not cause compilation failures. +// See https://github.com/rust-lang/rust/issues/30063 + +//@ ignore-cross-compile + +use run_make_support::{rustc, tmp_dir}; +use std::fs; + +fn compile(output_file: &str, emit: Option<&str>) { + let mut rustc = rustc(); + let rustc = rustc.codegen_units(4).output(tmp_dir().join(output_file)).input("foo.rs"); + if let Some(emit) = emit { + rustc.emit(emit); + } + rustc.run(); +} + +fn main() { + let flags = [ + ("foo-output", None), + ("asm-output", Some("asm")), + ("bc-output", Some("llvm-bc")), + ("ir-output", Some("llvm-ir")), + ("link-output", Some("link")), + ("obj-output", Some("obj")), + ("dep-output", Some("dep-info")), + ("multi-output", Some("asm,obj")), + ]; + for (output_file, emit) in flags { + fs::remove_file(output_file).unwrap_or_default(); + compile(output_file, emit); + fs::remove_file(output_file); + } +} diff --git a/tests/run-make/rustdoc-scrape-examples-macros/Makefile b/tests/run-make/rustdoc-scrape-examples-macros/Makefile deleted file mode 100644 index edc19d8cb5de4..0000000000000 --- a/tests/run-make/rustdoc-scrape-examples-macros/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-cross-compile -include ../../run-make/tools.mk - -OUTPUT_DIR := "$(TMPDIR)/rustdoc" -DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -) - -all: - $(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link - - $(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link - - $(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \ - --extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \ - -Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar - - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \ - -Z unstable-options --with-examples $(TMPDIR)/ex.calls - - $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs new file mode 100644 index 0000000000000..81b7defafc6c0 --- /dev/null +++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs @@ -0,0 +1,64 @@ +//@ ignore-cross-compile + +use run_make_support::{htmldocck, rustc, rustdoc, tmp_dir}; + +fn main() { + let tmp_dir = tmp_dir(); + let out_dir = tmp_dir.join("rustdoc"); + let ex_dir = tmp_dir.join("ex.calls"); + let proc_crate_name = "foobar_macro"; + let crate_name = "foobar"; + + let dylib_name = String::from_utf8( + rustc() + .crate_name(proc_crate_name) + .crate_type("dylib") + .arg("--print") + .arg("file-names") + .arg("-") + .command_output() + .stdout, + ) + .unwrap(); + + rustc() + .input("src/proc.rs") + .crate_name(proc_crate_name) + .edition("2021") + .crate_type("proc-macro") + .emit("dep-info,link") + .run(); + rustc() + .input("src/lib.rs") + .crate_name(crate_name) + .edition("2021") + .crate_type("lib") + .emit("dep-info,link") + .run(); + + rustdoc() + .input("examples/ex.rs") + .crate_name("ex") + .crate_type("bin") + .output(&out_dir) + .extern_(crate_name, tmp_dir.join(format!("lib{crate_name}.rlib"))) + .extern_(proc_crate_name, tmp_dir.join(dylib_name.trim())) + .arg("-Zunstable-options") + .arg("--scrape-examples-output-path") + .arg(&ex_dir) + .arg("--scrape-examples-target-crate") + .arg(crate_name) + .run(); + + rustdoc() + .input("src/lib.rs") + .crate_name(crate_name) + .crate_type("lib") + .output(&out_dir) + .arg("-Zunstable-options") + .arg("--with-examples") + .arg(&ex_dir) + .run(); + + assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success()); +} diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index 171850b89bb5e..7e247ce0c75d2 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -11,6 +11,7 @@ //@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_hir; #[macro_use] @@ -23,8 +24,8 @@ use rustc_smir::rustc_internal; use stable_mir::mir::mono::{Instance, InstanceKind}; use stable_mir::mir::visit::{Location, MirVisitor}; use stable_mir::mir::{LocalDecl, Terminator, TerminatorKind}; -use stable_mir::ty::{RigidTy, TyKind}; -use std::collections::HashSet; +use stable_mir::ty::{FnDef, GenericArgs, RigidTy, TyKind}; +use std::assert_matches::assert_matches; use std::convert::TryFrom; use std::io::Write; use std::ops::ControlFlow; @@ -39,9 +40,10 @@ fn test_intrinsics() -> ControlFlow<()> { visitor.visit_body(&main_body); let calls = visitor.calls; - assert_eq!(calls.len(), 2, "Expected 2 calls, but found: {calls:?}"); - for intrinsic in &calls { - check_intrinsic(intrinsic) + assert_eq!(calls.len(), 3, "Expected 3 calls, but found: {calls:?}"); + for (fn_def, args) in calls.into_iter() { + check_instance(&Instance::resolve(fn_def, &args).unwrap()); + check_def(fn_def); } ControlFlow::Continue(()) @@ -53,22 +55,39 @@ fn test_intrinsics() -> ControlFlow<()> { /// /// If by any chance this test breaks because you changed how an intrinsic is implemented, please /// update the test to invoke a different intrinsic. -fn check_intrinsic(intrinsic: &Instance) { - assert_eq!(intrinsic.kind, InstanceKind::Intrinsic); - let name = intrinsic.intrinsic_name().unwrap(); - if intrinsic.has_body() { - let Some(body) = intrinsic.body() else { unreachable!("Expected a body") }; +fn check_instance(instance: &Instance) { + assert_eq!(instance.kind, InstanceKind::Intrinsic); + let name = instance.intrinsic_name().unwrap(); + if instance.has_body() { + let Some(body) = instance.body() else { unreachable!("Expected a body") }; assert!(!body.blocks.is_empty()); - assert_eq!(&name, "likely"); + assert_matches!(name.as_str(), "likely" | "vtable_size"); } else { - assert!(intrinsic.body().is_none()); + assert!(instance.body().is_none()); assert_eq!(&name, "size_of_val"); } } +fn check_def(fn_def: FnDef) { + assert!(fn_def.is_intrinsic()); + let intrinsic = fn_def.as_intrinsic().unwrap(); + assert_eq!(fn_def, intrinsic.into()); + + let name = intrinsic.fn_name(); + match name.as_str() { + "likely" | "size_of_val" => { + assert!(!intrinsic.must_be_overridden()); + } + "vtable_size" => { + assert!(intrinsic.must_be_overridden()); + } + _ => unreachable!("Unexpected intrinsic: {}", name), + } +} + struct CallsVisitor<'a> { locals: &'a [LocalDecl], - calls: HashSet, + calls: Vec<(FnDef, GenericArgs)>, } impl<'a> MirVisitor for CallsVisitor<'a> { @@ -77,10 +96,10 @@ impl<'a> MirVisitor for CallsVisitor<'a> { TerminatorKind::Call { func, .. } => { let TyKind::RigidTy(RigidTy::FnDef(def, args)) = func.ty(self.locals).unwrap().kind() - else { - return; - }; - self.calls.insert(Instance::resolve(def, &args).unwrap()); + else { + return; + }; + self.calls.push((def, args.clone())); } _ => {} } @@ -106,6 +125,7 @@ fn generate_input(path: &str) -> std::io::Result<()> { #![feature(core_intrinsics)] use std::intrinsics::*; pub fn use_intrinsics(init: bool) -> bool {{ + let vtable_sz = unsafe {{ vtable_size(0 as *const ()) }}; let sz = unsafe {{ size_of_val("hi") }}; likely(init && sz == 2) }} diff --git a/tests/ui/async-await/async-is-unwindsafe.rs b/tests/ui/async-await/async-is-unwindsafe.rs index d0202f72f0086..53009b6e7410f 100644 --- a/tests/ui/async-await/async-is-unwindsafe.rs +++ b/tests/ui/async-await/async-is-unwindsafe.rs @@ -11,7 +11,6 @@ fn main() { is_unwindsafe(async { //~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary - //~| ERROR the type `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary use std::ptr::null; use std::task::{Context, RawWaker, RawWakerVTable, Waker}; let waker = unsafe { diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index 6bb06df9f39e9..5d87fc747682a 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -6,18 +6,19 @@ LL | is_unwindsafe(async { | |_____| | || LL | || -LL | || LL | || use std::ptr::null; +LL | || use std::task::{Context, RawWaker, RawWakerVTable, Waker}; ... || LL | || drop(cx_ref); LL | || }); | ||_____-^ `&mut Context<'_>` may not be safely transferred across an unwind boundary | |_____| - | within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}` + | within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}` | - = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}: UnwindSafe` + = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe` + = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>` note: future does not implement `UnwindSafe` as this value is used across an await - --> $DIR/async-is-unwindsafe.rs:26:18 + --> $DIR/async-is-unwindsafe.rs:25:18 | LL | let cx_ref = &mut cx; | ------ has type `&mut Context<'_>` which does not implement `UnwindSafe` @@ -30,38 +31,6 @@ note: required by a bound in `is_unwindsafe` LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe` -error[E0277]: the type `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary - --> $DIR/async-is-unwindsafe.rs:12:5 - | -LL | is_unwindsafe(async { - | _____^_____________- - | |_____| - | || -LL | || -LL | || -LL | || use std::ptr::null; -... || -LL | || drop(cx_ref); -LL | || }); - | ||_____-^ `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary - | |_____| - | within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}` - | - = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`, the trait `UnwindSafe` is not implemented for `&mut (dyn Any + 'static)`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}: UnwindSafe` -note: future does not implement `UnwindSafe` as this value is used across an await - --> $DIR/async-is-unwindsafe.rs:26:18 - | -LL | let mut cx = Context::from_waker(&waker); - | ------ has type `Context<'_>` which does not implement `UnwindSafe` -... -LL | async {}.await; // this needs an inner await point - | ^^^^^ await occurs here, with `mut cx` maybe used later -note: required by a bound in `is_unwindsafe` - --> $DIR/async-is-unwindsafe.rs:3:26 - | -LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} - | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/context-is-sorta-unwindsafe.rs b/tests/ui/async-await/context-is-sorta-unwindsafe.rs new file mode 100644 index 0000000000000..278476ea2379c --- /dev/null +++ b/tests/ui/async-await/context-is-sorta-unwindsafe.rs @@ -0,0 +1,14 @@ +//@ run-pass +// Tests against a regression surfaced by crater in https://github.com/rust-lang/rust/issues/125193 +// Unwind Safety is not a very coherent concept, but we'd prefer no regressions until we kibosh it +// and this is an unstable feature anyways sooo... + +use std::panic::UnwindSafe; +use std::task::Context; + +fn unwind_safe() {} + +fn main() { + unwind_safe::>(); // test UnwindSafe + unwind_safe::<&Context<'_>>(); // test RefUnwindSafe +} diff --git a/tests/ui/check-cfg/cargo-build-script.rs b/tests/ui/check-cfg/cargo-build-script.rs new file mode 100644 index 0000000000000..a3ba8791441e7 --- /dev/null +++ b/tests/ui/check-cfg/cargo-build-script.rs @@ -0,0 +1,22 @@ +// This test checks that when we are building a build script provided +// by Cargo we only suggest expecting the unexpected cfgs in the Cargo.toml. +// +//@ check-pass +//@ no-auto-check-cfg +//@ rustc-env:CARGO_CRATE_NAME=build_script_build +//@ compile-flags:--crate-name=build_script_build +//@ compile-flags:--check-cfg=cfg(has_bar) + +#[cfg(has_foo)] +//~^ WARNING unexpected `cfg` condition name +fn foo() {} + +#[cfg(has_foo = "yes")] +//~^ WARNING unexpected `cfg` condition name +fn foo() {} + +#[cfg(has_bar = "yes")] +//~^ WARNING unexpected `cfg` condition value +fn has_bar() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr new file mode 100644 index 0000000000000..9ab3290ef22e6 --- /dev/null +++ b/tests/ui/check-cfg/cargo-build-script.stderr @@ -0,0 +1,43 @@ +warning: unexpected `cfg` condition name: `has_foo` + --> $DIR/cargo-build-script.rs:10:7 + | +LL | #[cfg(has_foo)] + | ^^^^^^^ + | + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: consider using a Cargo feature instead + = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo)'] } + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name: `has_foo` + --> $DIR/cargo-build-script.rs:14:7 + | +LL | #[cfg(has_foo = "yes")] + | ^^^^^^^^^^^^^^^ + | + = help: consider using a Cargo feature instead + = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo, values("yes"))'] } + = note: see for more information about checking conditional configuration + +warning: unexpected `cfg` condition value: `yes` + --> $DIR/cargo-build-script.rs:18:7 + | +LL | #[cfg(has_bar = "yes")] + | ^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `has_bar` + = help: consider using a Cargo feature instead + = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_bar, values("yes"))'] } + = note: see for more information about checking conditional configuration + +warning: 3 warnings emitted + diff --git a/tests/ui/consts/const-int-unchecked.stderr b/tests/ui/consts/const-int-unchecked.stderr index 84b222972a13c..3130603231e1b 100644 --- a/tests/ui/consts/const-int-unchecked.stderr +++ b/tests/ui/consts/const-int-unchecked.stderr @@ -242,19 +242,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:123:25 | LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:126:25 | LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:129:25 | LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:132:25 diff --git a/tests/ui/consts/erroneous_type_in_const_return_value.rs b/tests/ui/consts/erroneous_type_in_const_return_value.rs new file mode 100644 index 0000000000000..304211f77da72 --- /dev/null +++ b/tests/ui/consts/erroneous_type_in_const_return_value.rs @@ -0,0 +1,12 @@ +//! ICE test #124348 +//! We should not be running const eval if the layout has errors. + +enum Eek { + TheConst, + UnusedByTheConst(Sum), + //~^ ERROR cannot find type `Sum` in this scope +} + +const EEK_ZERO: &[Eek] = &[]; + +fn main() {} diff --git a/tests/ui/consts/erroneous_type_in_const_return_value.stderr b/tests/ui/consts/erroneous_type_in_const_return_value.stderr new file mode 100644 index 0000000000000..453f5b640973f --- /dev/null +++ b/tests/ui/consts/erroneous_type_in_const_return_value.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Sum` in this scope + --> $DIR/erroneous_type_in_const_return_value.rs:6:22 + | +LL | UnusedByTheConst(Sum), + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL + use std::iter::Sum; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/consts/erroneous_type_in_promoted.rs b/tests/ui/consts/erroneous_type_in_promoted.rs new file mode 100644 index 0000000000000..32e33c2030fbb --- /dev/null +++ b/tests/ui/consts/erroneous_type_in_promoted.rs @@ -0,0 +1,14 @@ +//! ICE test #124348 +//! We should not be running const eval if the layout has errors. + +enum Eek { + TheConst, + UnusedByTheConst(Sum), + //~^ ERROR cannot find type `Sum` in this scope +} + +const fn foo() { + let x: &'static [Eek] = &[]; +} + +fn main() {} diff --git a/tests/ui/consts/erroneous_type_in_promoted.stderr b/tests/ui/consts/erroneous_type_in_promoted.stderr new file mode 100644 index 0000000000000..0601fc9ebe7fb --- /dev/null +++ b/tests/ui/consts/erroneous_type_in_promoted.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Sum` in this scope + --> $DIR/erroneous_type_in_promoted.rs:6:22 + | +LL | UnusedByTheConst(Sum), + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL + use std::iter::Sum; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 2785b12a0aef4..6ad3effe0e26e 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,13 +1,6 @@ error: extern location for std does not exist: -error: `#[panic_handler]` function required, but not found - -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - error: requires `sized` lang_item -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs new file mode 100644 index 0000000000000..5250e3a3d93e6 --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs @@ -0,0 +1,57 @@ +//! Test that coercing between function items of different functions works, +//! as long as their signatures match. The resulting value is a function pointer. + +#![feature(type_alias_impl_trait)] + +fn foo(t: T) -> T { + t +} + +fn bar(t: T) -> T { + t +} + +type F = impl Sized; + +fn f(a: F) { + let mut x = bar::; + x = foo::<()>; //~ ERROR: mismatched types + x(a); + x(()); +} + +type I = impl Sized; + +fn i(a: I) { + let mut x = bar::<()>; + x = foo::; //~ ERROR: mismatched types + x(a); + x(()); +} + +type J = impl Sized; + +fn j(a: J) { + let x = match true { + true => bar::, + false => foo::<()>, + }; + x(a); + x(()); +} + +fn k() -> impl Sized { + fn bind T>(_: T, f: F) -> F { + f + } + let x = match true { + true => { + let f = foo; + bind(k(), f) + } + false => bar::<()>, + }; + todo!() +} + +fn main() {} diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr new file mode 100644 index 0000000000000..0b3331b040d85 --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:18:9 + | +LL | type F = impl Sized; + | ---------- the expected opaque type +... +LL | let mut x = bar::; + | -------- expected due to this value +LL | x = foo::<()>; + | ^^^^^^^^^ expected fn item, found a different fn item + | + = note: expected fn item `fn(F) -> F {bar::}` + found fn item `fn(()) {foo::<()>}` + +error[E0308]: mismatched types + --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9 + | +LL | fn foo(t: T) -> T { + | -------------------- function `foo` defined here +... +LL | type I = impl Sized; + | ---------- the found opaque type +... +LL | let mut x = bar::<()>; + | --------- expected due to this value +LL | x = foo::; + | ^^^^^^^^ expected fn item, found a different fn item + | + = note: expected fn item `fn(()) {bar::<()>}` + found fn item `fn(I) -> I {foo::}` +help: use parentheses to call this function + | +LL | x = foo::(/* I */); + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.rs b/tests/ui/inference/note-and-explain-ReVar-124973.rs new file mode 100644 index 0000000000000..f1e2464563699 --- /dev/null +++ b/tests/ui/inference/note-and-explain-ReVar-124973.rs @@ -0,0 +1,8 @@ +//@ edition:2018 + +#![feature(c_variadic)] + +async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {} +//~^ ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds + +fn main() {} diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.stderr b/tests/ui/inference/note-and-explain-ReVar-124973.stderr new file mode 100644 index 0000000000000..574f6508e4c78 --- /dev/null +++ b/tests/ui/inference/note-and-explain-ReVar-124973.stderr @@ -0,0 +1,13 @@ +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/note-and-explain-ReVar-124973.rs:5:73 + | +LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {} + | ----------------------------------------------------------------------- ^^ + | | + | opaque type defined here + | + = note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/lint/for_loop_over_fallibles.rs b/tests/ui/lint/for_loop_over_fallibles.rs index 52c3b8f2aae5f..89ac20c352178 100644 --- a/tests/ui/lint/for_loop_over_fallibles.rs +++ b/tests/ui/lint/for_loop_over_fallibles.rs @@ -41,3 +41,25 @@ fn _returns_result() -> Result<(), ()> { Ok(()) } + +fn _by_ref() { + // Shared refs + for _ in &Some(1) {} + //~^ WARN for loop over a `&Option`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + for _ in &Ok::<_, ()>(1) {} + //~^ WARN for loop over a `&Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + + // Mutable refs + for _ in &mut Some(1) {} + //~^ WARN for loop over a `&mut Option`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + for _ in &mut Ok::<_, ()>(1) {} + //~^ WARN for loop over a `&mut Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent +} diff --git a/tests/ui/lint/for_loop_over_fallibles.stderr b/tests/ui/lint/for_loop_over_fallibles.stderr index 96efdf85c4901..f695de082572a 100644 --- a/tests/ui/lint/for_loop_over_fallibles.stderr +++ b/tests/ui/lint/for_loop_over_fallibles.stderr @@ -97,5 +97,65 @@ help: consider using `if let` to clear intent LL | if let Ok(_) = Ok::<_, ()>([0; 0]) {} | ~~~~~~~~~~ ~~~ -warning: 6 warnings emitted +warning: for loop over a `&Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:47:14 + | +LL | for _ in &Some(1) {} + | ^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Some(_) = &Some(1) {} + | ~~~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = &Some(1) {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `&Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:51:14 + | +LL | for _ in &Ok::<_, ()>(1) {} + | ^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = &Ok::<_, ()>(1) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = &Ok::<_, ()>(1) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over a `&mut Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:57:14 + | +LL | for _ in &mut Some(1) {} + | ^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Some(_) = &mut Some(1) {} + | ~~~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = &mut Some(1) {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `&mut Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:61:14 + | +LL | for _ in &mut Ok::<_, ()>(1) {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = &mut Ok::<_, ()>(1) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = &mut Ok::<_, ()>(1) {} + | ~~~~~~~~~~ ~~~ + +warning: 10 warnings emitted diff --git a/tests/ui/lint/missing_copy_impl_trivial_bounds.rs b/tests/ui/lint/missing_copy_impl_trivial_bounds.rs new file mode 100644 index 0000000000000..9b743417bd52b --- /dev/null +++ b/tests/ui/lint/missing_copy_impl_trivial_bounds.rs @@ -0,0 +1,21 @@ +//@ check-pass + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +// Make sure that we still use the where-clauses from the struct when checking +// if it may implement `Copy` unconditionally. +// Fix for . + +pub trait Foo { + type Assoc; +} + +pub struct Bar; + +// This needs to be public +pub struct Baz2(::Assoc) +where + Bar: Foo; + +fn main() {} diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.fixed b/tests/ui/loops/loop-if-else-break-issue-123261.fixed new file mode 100644 index 0000000000000..f9e88c18ad02c --- /dev/null +++ b/tests/ui/loops/loop-if-else-break-issue-123261.fixed @@ -0,0 +1,31 @@ +//@ run-rustfix + +#![allow(unused)] + +fn main() { + let n = 1; + let m = 2; + let x = 'block: { + if n == 0 { + break 'block 1; //~ ERROR [E0268] + } else { + break 'block 2; + } + }; + + let y = 'block: { + if n == 0 { + break 'block 1; //~ ERROR [E0268] + } + break 'block 0; + }; + + let z = 'block: { + if n == 0 { + if m > 1 { + break 'block 3; //~ ERROR [E0268] + } + } + break 'block 1; + }; +} diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.rs b/tests/ui/loops/loop-if-else-break-issue-123261.rs new file mode 100644 index 0000000000000..a1f9dabe891fd --- /dev/null +++ b/tests/ui/loops/loop-if-else-break-issue-123261.rs @@ -0,0 +1,31 @@ +//@ run-rustfix + +#![allow(unused)] + +fn main() { + let n = 1; + let m = 2; + let x = { + if n == 0 { + break 1; //~ ERROR [E0268] + } else { + break 2; + } + }; + + let y = { + if n == 0 { + break 1; //~ ERROR [E0268] + } + break 0; + }; + + let z = { + if n == 0 { + if m > 1 { + break 3; //~ ERROR [E0268] + } + } + break 1; + }; +} diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.stderr b/tests/ui/loops/loop-if-else-break-issue-123261.stderr new file mode 100644 index 0000000000000..7bd192fc00b0d --- /dev/null +++ b/tests/ui/loops/loop-if-else-break-issue-123261.stderr @@ -0,0 +1,59 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/loop-if-else-break-issue-123261.rs:10:13 + | +LL | break 1; + | ^^^^^^^ cannot `break` outside of a loop or labeled block +LL | } else { +LL | break 2; + | ^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ let x = 'block: { +LL | if n == 0 { +LL ~ break 'block 1; +LL | } else { +LL ~ break 'block 2; + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/loop-if-else-break-issue-123261.rs:18:13 + | +LL | break 1; + | ^^^^^^^ cannot `break` outside of a loop or labeled block +LL | } +LL | break 0; + | ^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ let y = 'block: { +LL | if n == 0 { +LL ~ break 'block 1; +LL | } +LL ~ break 'block 0; + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/loop-if-else-break-issue-123261.rs:26:17 + | +LL | break 3; + | ^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | break 1; + | ^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ let z = 'block: { +LL | if n == 0 { +LL | if m > 1 { +LL ~ break 'block 3; +LL | } +LL | } +LL ~ break 'block 1; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr index 9407e8ac0029d..2f46cb36750be 100644 --- a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr +++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr @@ -21,16 +21,21 @@ LL | foo!(()); = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0268]: `break` outside of a loop or labeled block - --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19 - | -LL | foo!(stmt break ()); - | ^^^^^^^^ cannot `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17 | -help: consider labeling this block to be able to break within it +LL | foo!(=> break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17 | -LL ~ 'block: { -LL ~ foo!(stmt break 'block ()); +LL | break () + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | bar!() + | ------ in this macro invocation | + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:12:11 @@ -48,21 +53,16 @@ LL | 'block: { break 'block $e; } | +++++++ ++++++ error[E0268]: `break` outside of a loop or labeled block - --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17 + --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19 | -LL | foo!(=> break ()); - | ^^^^^^^^ cannot `break` outside of a loop or labeled block - -error[E0268]: `break` outside of a loop or labeled block - --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17 +LL | foo!(stmt break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block | -LL | break () - | ^^^^^^^^ cannot `break` outside of a loop or labeled block -... -LL | bar!() - | ------ in this macro invocation +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ foo!(stmt break 'block ()); | - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs new file mode 100644 index 0000000000000..ed76815a6ac8e --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs @@ -0,0 +1,9 @@ +//@ aux-crate:shared=shared.rs + +extern crate shared; + +pub use shared::Shared; + +pub struct SharedInType { + pub f: Shared +} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs new file mode 100644 index 0000000000000..ed76815a6ac8e --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs @@ -0,0 +1,9 @@ +//@ aux-crate:shared=shared.rs + +extern crate shared; + +pub use shared::Shared; + +pub struct SharedInType { + pub f: Shared +} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs new file mode 100644 index 0000000000000..0e4a73c7fc011 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs @@ -0,0 +1,4 @@ +//@ aux-crate:priv:indirect2=indirect2.rs +//@ compile-flags: -Zunstable-options + +extern crate indirect2; diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs new file mode 100644 index 0000000000000..5f6b289eb1414 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs @@ -0,0 +1,4 @@ +//@ aux-crate:shared=shared.rs + +// This is public. +extern crate shared; diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs new file mode 100644 index 0000000000000..9e2aa898afe8d --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs @@ -0,0 +1,22 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn fn_like(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[proc_macro_derive(PmDerive)] +pub fn pm_derive(item: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn pm_attr(attr: TokenStream, item: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs index e7afeb84fb4f4..4eeecdc056972 100644 --- a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs @@ -1,2 +1,11 @@ pub struct OtherType; pub trait OtherTrait {} + +#[macro_export] +macro_rules! m { + () => {}; +} + +pub enum E { + V1 +} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs new file mode 100644 index 0000000000000..0655e3ae2cfdb --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs @@ -0,0 +1,5 @@ +//@ aux-crate:shared=shared.rs + +extern crate shared; + +pub use shared::Shared; diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs new file mode 100644 index 0000000000000..efc4daa7befb8 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs @@ -0,0 +1 @@ +pub struct Shared; diff --git a/tests/ui/privacy/pub-priv-dep/diamond_deps.rs b/tests/ui/privacy/pub-priv-dep/diamond_deps.rs new file mode 100644 index 0000000000000..0e1f6f36bc8cc --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/diamond_deps.rs @@ -0,0 +1,48 @@ +//@ aux-crate:priv:diamond_priv_dep=diamond_priv_dep.rs +//@ aux-crate:diamond_pub_dep=diamond_pub_dep.rs +//@ compile-flags: -Zunstable-options + +// A diamond dependency: +// +// diamond_reepxort +// /\ +// (public) / \ (PRIVATE) +// / \ +// diamond_pub_dep diamond_priv_dep +// \ / +// (public) \ / (public) +// \/ +// shared +// +// Where the pub and private crates reexport something from the shared crate. +// +// Checks the behavior when the same shared item appears in the public API, +// depending on whether it comes from the public side or the private side. +// +// NOTE: compiletest does not support deduplicating shared dependencies. +// However, it should work well enough for this test, the only downside is +// that diamond_shared gets built twice. + +#![crate_type = "lib"] +#![deny(exported_private_dependencies)] + +extern crate diamond_priv_dep; +extern crate diamond_pub_dep; + +// FIXME: This should trigger. +pub fn leaks_priv() -> diamond_priv_dep::Shared { + diamond_priv_dep::Shared +} + +pub fn leaks_pub() -> diamond_pub_dep::Shared { + diamond_pub_dep::Shared +} + +pub struct PrivInStruct { + pub f: diamond_priv_dep::SharedInType +//~^ ERROR type `diamond_priv_dep::SharedInType` from private dependency 'diamond_priv_dep' in public interface +} + +pub struct PubInStruct { + pub f: diamond_pub_dep::SharedInType +} diff --git a/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr b/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr new file mode 100644 index 0000000000000..8a6d35a747b63 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr @@ -0,0 +1,14 @@ +error: type `diamond_priv_dep::SharedInType` from private dependency 'diamond_priv_dep' in public interface + --> $DIR/diamond_deps.rs:42:5 + | +LL | pub f: diamond_priv_dep::SharedInType + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/diamond_deps.rs:27:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index f26dbb47ba5e9..112eaf528be27 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -1,12 +1,20 @@ //@ aux-crate:priv:priv_dep=priv_dep.rs //@ aux-build:pub_dep.rs +//@ aux-crate:priv:pm=pm.rs //@ compile-flags: -Zunstable-options + +// Basic behavior check of exported_private_dependencies from either a public +// dependency or a private one. + #![deny(exported_private_dependencies)] // This crate is a private dependency -extern crate priv_dep; +// FIXME: This should trigger. +pub extern crate priv_dep; // This crate is a public dependency extern crate pub_dep; +// This crate is a private dependency +extern crate pm; use priv_dep::{OtherTrait, OtherType}; use pub_dep::PubType; @@ -25,7 +33,10 @@ pub struct PublicType { } impl PublicType { - pub fn pub_fn(param: OtherType) {} + pub fn pub_fn_param(param: OtherType) {} + //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + + pub fn pub_fn_return() -> OtherType { OtherType } //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface fn priv_fn(param: OtherType) {} @@ -36,9 +47,61 @@ pub trait MyPubTrait { } //~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface +pub trait WithSuperTrait: OtherTrait {} +//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface + +pub trait PubLocalTraitWithAssoc { + type X; +} + +pub struct PrivateAssoc; +impl PubLocalTraitWithAssoc for PrivateAssoc { + type X = OtherType; +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface +} + +pub fn in_bounds(x: T) { unimplemented!() } +//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface + +pub fn private_in_generic() -> std::num::Saturating { unimplemented!() } +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + +pub static STATIC: OtherType = OtherType; +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + +pub const CONST: OtherType = OtherType; +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + +pub type Alias = OtherType; +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + +pub struct PublicWithPrivateImpl; + +// FIXME: This should trigger. +// See https://github.com/rust-lang/rust/issues/71043 +impl OtherTrait for PublicWithPrivateImpl {} + +pub trait PubTraitOnPrivate {} + +// FIXME: This should trigger. +// See https://github.com/rust-lang/rust/issues/71043 +impl PubTraitOnPrivate for OtherType {} + pub struct AllowedPrivType { #[allow(exported_private_dependencies)] pub allowed: OtherType, } +// FIXME: This should trigger. +pub use priv_dep::m; +// FIXME: This should trigger. +pub use pm::fn_like; +// FIXME: This should trigger. +pub use pm::PmDerive; +// FIXME: This should trigger. +pub use pm::pm_attr; + +// FIXME: This should trigger. +pub use priv_dep::E::V1; + fn main() {} diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index e62a440d8f568..53d461a5774a0 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -1,26 +1,74 @@ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:21:5 + --> $DIR/pub-priv1.rs:29:5 | LL | pub field: OtherType, | ^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/pub-priv1.rs:4:9 + --> $DIR/pub-priv1.rs:9:9 | LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:28:5 + --> $DIR/pub-priv1.rs:36:5 | -LL | pub fn pub_fn(param: OtherType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub fn pub_fn_param(param: OtherType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:39:5 + | +LL | pub fn pub_fn_return() -> OtherType { OtherType } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:35:5 + --> $DIR/pub-priv1.rs:46:5 | LL | type Foo: OtherTrait; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:50:1 + | +LL | pub trait WithSuperTrait: OtherTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:59:5 + | +LL | type X = OtherType; + | ^^^^^^ + +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:63:1 + | +LL | pub fn in_bounds(x: T) { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:66:1 + | +LL | pub fn private_in_generic() -> std::num::Saturating { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:69:1 + | +LL | pub static STATIC: OtherType = OtherType; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:72:1 + | +LL | pub const CONST: OtherType = OtherType; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:75:1 + | +LL | pub type Alias = OtherType; + | ^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs new file mode 100644 index 0000000000000..3c6e9825e7288 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs @@ -0,0 +1,15 @@ +//@ aux-crate:priv:reexport=reexport.rs +//@ compile-flags: -Zunstable-options +//@ check-pass + +// Checks the behavior of a reexported item from a private dependency. + +#![crate_type = "lib"] +#![deny(exported_private_dependencies)] + +extern crate reexport; + +// FIXME: This should trigger. +pub fn leaks_priv() -> reexport::Shared { + reexport::Shared +} diff --git a/tests/ui/privacy/pub-priv-dep/shared_both_private.rs b/tests/ui/privacy/pub-priv-dep/shared_both_private.rs new file mode 100644 index 0000000000000..20a4b85c01e8d --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/shared_both_private.rs @@ -0,0 +1,32 @@ +//@ aux-crate:priv:shared=shared.rs +//@ aux-crate:reexport=reexport.rs +//@ compile-flags: -Zunstable-options +//@ check-pass + +// A shared dependency, where a private dependency reexports a public dependency. +// +// shared_both_private +// /\ +// (PRIVATE) / | (PRIVATE) +// / | +// reexport | +// \ | +// (public) \ / +// \/ +// shared + +#![crate_type = "lib"] +#![deny(exported_private_dependencies)] + +extern crate shared; +extern crate reexport; + +// FIXME: This should trigger. +pub fn leaks_priv() -> shared::Shared { + shared::Shared +} + +// FIXME: This should trigger. +pub fn leaks_priv_reexport() -> reexport::Shared { + reexport::Shared +} diff --git a/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs b/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs new file mode 100644 index 0000000000000..b329a7acb5834 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs @@ -0,0 +1,39 @@ +//@ aux-crate:priv:shared=shared.rs +//@ aux-crate:reexport=reexport.rs +//@ compile-flags: -Zunstable-options +//@ check-pass + +// A shared dependency, where the public side reexports the same item as a +// direct private dependency. +// +// shared_direct_private +// /\ +// (public) / | (PRIVATE) +// / | +// reexport | +// \ | +// (public) \ / +// \/ +// shared +// + +#![crate_type = "lib"] +#![deny(exported_private_dependencies)] + +extern crate shared; +extern crate reexport; + +// FIXME: Should this trigger? +// +// One could make an argument that I said I want "reexport" to be public, and +// since "reexport" says "shared_direct_private" is public, then it should +// transitively be public for me. However, as written, this is explicitly +// referring to a dependency that is marked "private", which I think is +// confusing. +pub fn leaks_priv() -> shared::Shared { + shared::Shared +} + +pub fn leaks_pub() -> reexport::Shared { + reexport::Shared +} diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs new file mode 100644 index 0000000000000..34b624b4a1a40 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs @@ -0,0 +1,29 @@ +//@ aux-crate:priv:shared=shared.rs +//@ aux-crate:priv:indirect1=indirect1.rs +//@ compile-flags: -Zunstable-options +//@ check-pass + +// A shared dependency, where it is only indirectly public. +// +// shared_indirect +// /\ +// (PRIVATE) / | (PRIVATE) +// / | +// indirect1 | | +// (PRIVATE) | | +// indirect2 | | +// \ | +// (public) \ / +// \/ +// shared + +#![crate_type = "lib"] +#![deny(exported_private_dependencies)] + +extern crate shared; +extern crate indirect1; + +// FIXME: This should trigger. +pub fn leaks_priv() -> shared::Shared { + shared::Shared +} diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr index c7fadc6f92931..3fa5b0f9aef3e 100644 --- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr @@ -22,7 +22,7 @@ note: the crate import `core` is defined here LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ -error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub` +error[E0365]: extern crate `core` is private, and cannot be re-exported, consider declaring with `pub` --> $DIR/pub-reexport-priv-extern-crate.rs:2:9 | LL | pub use core as reexported_core; @@ -34,4 +34,5 @@ LL | pub use core as reexported_core; error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0603`. +Some errors have detailed explanations: E0365, E0603. +For more information about an error, try `rustc --explain E0365`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr index aa660db38679c..537819ab8595c 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr @@ -91,7 +91,7 @@ LL | const _: () = sse2_and_fxsr(); = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` -error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block --> $DIR/safe-calls.rs:70:5 | LL | sse2(); diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs deleted file mode 100644 index 372ebf2cff97f..0000000000000 --- a/tests/ui/threads-sendsync/issue-43733-2.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ needs-threads -//@ dont-check-compiler-stderr -#![feature(cfg_target_thread_local, thread_local_internals)] - -// On platforms *without* `#[thread_local]`, use -// a custom non-`Sync` type to fake the same error. -#[cfg(not(target_thread_local))] -struct Key { - _data: std::cell::UnsafeCell>, - _flag: std::cell::Cell<()>, -} - -#[cfg(not(target_thread_local))] -impl Key { - const fn new() -> Self { - Key { - _data: std::cell::UnsafeCell::new(None), - _flag: std::cell::Cell::new(()), - } - } -} - -#[cfg(target_thread_local)] -use std::thread::local_impl::Key; - -static __KEY: Key<()> = Key::new(); -//~^ ERROR `UnsafeCell>` cannot be shared between threads -//~| ERROR cannot be shared between threads safely [E0277] - -fn main() {} diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs deleted file mode 100644 index c90f60887cfd2..0000000000000 --- a/tests/ui/threads-sendsync/issue-43733.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ needs-threads -#![feature(thread_local)] -#![feature(cfg_target_thread_local, thread_local_internals)] - -use std::cell::RefCell; - -type Foo = std::cell::RefCell; - -#[cfg(target_thread_local)] -#[thread_local] -static __KEY: std::thread::local_impl::Key = std::thread::local_impl::Key::new(); - -#[cfg(not(target_thread_local))] -static __KEY: std::thread::local_impl::Key = std::thread::local_impl::Key::new(); - -fn __getit(_: Option<&mut Option>>) -> std::option::Option<&'static Foo> { - __KEY.get(Default::default) - //~^ ERROR call to unsafe function `Key::::get` is unsafe -} - -static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); -//~^ ERROR call to unsafe function `LocalKey::::new` is unsafe - -fn main() { - FOO.with(|foo| println!("{}", foo.borrow())); - std::thread::spawn(|| { - FOO.with(|foo| *foo.borrow_mut() += "foo"); - }) - .join() - .unwrap(); - FOO.with(|foo| println!("{}", foo.borrow())); -} diff --git a/tests/ui/threads-sendsync/issue-43733.stderr b/tests/ui/threads-sendsync/issue-43733.stderr deleted file mode 100644 index 9b13646a22852..0000000000000 --- a/tests/ui/threads-sendsync/issue-43733.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function `Key::::get` is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:17:5 - | -LL | __KEY.get(Default::default) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function `LocalKey::::new` is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:21:42 - | -LL | static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr index 2eb1754392e1a..fe12dd72d9ebe 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr @@ -1,4 +1,4 @@ -warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +warning[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:10:5 | LL | unsf(); @@ -15,3 +15,4 @@ LL | unsafe fn foo() { warning: 1 warning emitted +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr index e6d1d4e5cc780..05f36ab47cb56 100644 --- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr +++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr @@ -1,4 +1,4 @@ -warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +warning[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/edition_2024_default.rs:13:5 | LL | unsf(); @@ -15,3 +15,4 @@ LL | unsafe fn foo() { warning: 1 warning emitted +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr index 5092c1e689d67..3f97199458da4 100644 --- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr +++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr @@ -1,4 +1,4 @@ -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/in_2024_compatibility.rs:7:5 | LL | unsf(); @@ -20,3 +20,4 @@ LL | #![deny(rust_2024_compatibility)] error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr index 4bc604a110ea1..1f80342566ca3 100644 --- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr +++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr @@ -1,4 +1,4 @@ -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:9:5 | LL | unsf(); @@ -17,7 +17,7 @@ note: the lint level is defined here LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) +error[E0133]: dereference of raw pointer is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:5 | LL | *PTR; @@ -26,7 +26,7 @@ LL | *PTR; = note: for more information, see issue #71668 = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: use of mutable static is unsafe and requires unsafe block (error E0133) +error[E0133]: use of mutable static is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:13:5 | LL | VOID = (); @@ -47,7 +47,7 @@ note: the lint level is defined here LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5 | LL | unsf(); @@ -67,7 +67,7 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]` -error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) +error[E0133]: dereference of raw pointer is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5 | LL | *PTR; @@ -76,7 +76,7 @@ LL | *PTR; = note: for more information, see issue #71668 = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: use of mutable static is unsafe and requires unsafe block (error E0133) +error[E0133]: use of mutable static is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5 | LL | VOID = (); diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr index b9f5969474d00..1ce22ecfdc796 100644 --- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr @@ -1,4 +1,4 @@ -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:13:5 | LL | unsf(); @@ -17,7 +17,7 @@ note: the lint level is defined here LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:17:5 | LL | unsf(); @@ -26,7 +26,7 @@ LL | unsf(); = note: for more information, see issue #71668 = note: consult the function's documentation for information on how to avoid undefined behavior -error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) +error[E0133]: dereference of raw pointer is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:25:13 | LL | let y = *x; @@ -40,7 +40,7 @@ note: an unsafe function restricts its caller, but its body is safe by default LL | pub unsafe fn bar(x: *const i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) +error[E0133]: dereference of raw pointer is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:29:9 | LL | y + *x @@ -49,7 +49,7 @@ LL | y + *x = note: for more information, see issue #71668 = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: use of mutable static is unsafe and requires unsafe block (error E0133) +error[E0133]: use of mutable static is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:38:13 | LL | let y = BAZ; @@ -63,7 +63,7 @@ note: an unsafe function restricts its caller, but its body is safe by default LL | pub unsafe fn baz() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of mutable static is unsafe and requires unsafe block (error E0133) +error[E0133]: use of mutable static is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:42:9 | LL | y + BAZ @@ -72,7 +72,7 @@ LL | y + BAZ = note: for more information, see issue #71668 = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:48:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } @@ -90,7 +90,7 @@ LL | pub unsafe fn unsafe_in_macro() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:48:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } @@ -105,3 +105,4 @@ LL | unsafe_macro!(); error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0133`. diff --git a/triagebot.toml b/triagebot.toml index 2e45b257f8126..95fa3befe60f2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -842,6 +842,9 @@ cc = ["@Zalathar"] message = "Some changes occurred in coverage tests." cc = ["@Zalathar"] +[mentions."src/tools/opt-dist"] +cc = ["@kobzol"] + [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" @@ -1059,6 +1062,7 @@ project-exploit-mitigations = [ "/src/tools/cargo" = ["@ehuss"] "/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors", "@jieyouxu"] "/src/tools/linkchecker" = ["@ehuss"] +"/src/tools/opt-dist" = ["@kobzol"] "/src/tools/run-make-support" = ["@jieyouxu"] "/src/tools/rust-installer" = ["bootstrap"] "/src/tools/rustbook" = ["@ehuss"]